chiark / gitweb /
math/gfx-sqr.c: Use bithacking rather than a table for squaring.
[catacomb] / symm / cfb-def.h
1 /* -*-c-*-
2  *
3  * Definitions for ciphertext feedback mode
4  *
5  * (c) 1999 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
9  *
10  * This file is part of Catacomb.
11  *
12  * Catacomb is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU Library General Public License as
14  * published by the Free Software Foundation; either version 2 of the
15  * License, or (at your option) any later version.
16  *
17  * Catacomb is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public
23  * License along with Catacomb; if not, write to the Free
24  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25  * MA 02111-1307, USA.
26  */
27
28 #ifndef CATACOMB_CFB_DEF_H
29 #define CATACOMB_CFB_DEF_H
30
31 #ifdef __cplusplus
32   extern "C" {
33 #endif
34
35 /*----- Header files ------------------------------------------------------*/
36
37 #include <string.h>
38
39 #include <mLib/bits.h>
40 #include <mLib/sub.h>
41
42 #ifndef CATACOMB_ARENA_H
43 #  include "arena.h"
44 #endif
45
46 #ifndef CATACOMB_BLKC_H
47 #  include "blkc.h"
48 #endif
49
50 #ifndef CATACOMB_GCIPHER_H
51 #  include "gcipher.h"
52 #endif
53
54 #ifndef CATACOMB_PARANOIA_H
55 #  include "paranoia.h"
56 #endif
57
58 #ifndef CATACOMB_PARANOIA_H
59 #  include "paranoia.h"
60 #endif
61
62 #ifndef CATACOMB_RSVR_H
63 #  include "rsvr.h"
64 #endif
65
66 /*----- Macros ------------------------------------------------------------*/
67
68 /* --- @CFB_DEF@ --- *
69  *
70  * Arguments:   @PRE@, @pre@ = prefixes for the underlying block cipher
71  *
72  * Use:         Creates an implementation for CFB mode.
73  */
74
75 #define CFB_DEF(PRE, pre) CFB_DEFX(PRE, pre, #pre, #pre)
76
77 #define CFB_DEFX(PRE, pre, name, fname)                                 \
78                                                                         \
79 /* --- @pre_cfbgetiv@ --- *                                             \
80  *                                                                      \
81  * Arguments:   @const pre_cfbctx *ctx@ = pointer to CFB context block  \
82  *              @void *iv@ = pointer to output data block               \
83  *                                                                      \
84  * Returns:     ---                                                     \
85  *                                                                      \
86  * Use:         Reads the currently set IV.  Reading and setting an IV  \
87  *              is not transparent to the cipher.  It will add a `step' \
88  *              which must be matched by a similar operation during     \
89  *              decryption.                                             \
90  */                                                                     \
91                                                                         \
92 void pre##_cfbgetiv(const pre##_cfbctx *ctx, void *iv)                  \
93 {                                                                       \
94   octet *p = iv;                                                        \
95   unsigned off = ctx->off;                                              \
96   unsigned rest = PRE##_BLKSZ - off;                                    \
97                                                                         \
98   memcpy(p, ctx->b + off, rest);                                        \
99   memcpy(p + rest, ctx->b, off);                                        \
100 }                                                                       \
101                                                                         \
102 /* --- @pre_cfbsetiv@ --- *                                             \
103  *                                                                      \
104  * Arguments:   @pre_cfbctx *ctx@ = pointer to CFB context block        \
105  *              @cnost void *iv@ = pointer to IV to set                 \
106  *                                                                      \
107  * Returns:     ---                                                     \
108  *                                                                      \
109  * Use:         Sets the IV to use for subsequent encryption.           \
110  */                                                                     \
111                                                                         \
112 void pre##_cfbsetiv(pre##_cfbctx *ctx, const void *iv)                  \
113   { memcpy(ctx->b, iv, PRE##_BLKSZ); ctx->off = 0; }                    \
114                                                                         \
115 /* --- @pre_cfbbdry@ --- *                                              \
116  *                                                                      \
117  * Arguments:   @pre_cfbctx *ctx@ = pointer to CFB context block        \
118  *                                                                      \
119  * Returns:     ---                                                     \
120  *                                                                      \
121  * Use:         Inserts a boundary during encryption.  Successful       \
122  *              decryption must place a similar boundary.               \
123  */                                                                     \
124                                                                         \
125 void pre##_cfbbdry(pre##_cfbctx *ctx)                                   \
126 {                                                                       \
127   uint32 t[PRE##_BLKSZ/4];                                              \
128                                                                         \
129   BLKC_LOAD(PRE, t, ctx->b);                                            \
130   pre##_eblk(&ctx->ctx, t, t);                                          \
131   BLKC_STORE(PRE, ctx->b, t);                                           \
132   ctx->off = 0;                                                         \
133   BURN(t);                                                              \
134 }                                                                       \
135                                                                         \
136 /* --- @pre_cfbsetkey@ --- *                                            \
137  *                                                                      \
138  * Arguments:   @pre_cfbctx *ctx@ = pointer to CFB context block        \
139  *              @const pre_ctx *k@ = pointer to cipher context          \
140  *                                                                      \
141  * Returns:     ---                                                     \
142  *                                                                      \
143  * Use:         Sets the CFB context to use a different cipher key.     \
144  */                                                                     \
145                                                                         \
146 void pre##_cfbsetkey(pre##_cfbctx *ctx, const pre##_ctx *k)             \
147   { ctx->ctx = *k; ctx->off = 0; }                                      \
148                                                                         \
149 /* --- @pre_cfbinit@ --- *                                              \
150  *                                                                      \
151  * Arguments:   @pre_cfbctx *ctx@ = pointer to cipher context           \
152  *              @const void *key@ = pointer to the key buffer           \
153  *              @size_t sz@ = size of the key                           \
154  *              @const void *iv@ = pointer to initialization vector     \
155  *                                                                      \
156  * Returns:     ---                                                     \
157  *                                                                      \
158  * Use:         Initializes a CFB context ready for use.  You should    \
159  *              ensure that the IV chosen is unique: reusing an IV will \
160  *              compromise the security of at least the first block     \
161  *              encrypted.  This is equivalent to calls to @pre_init@,  \
162  *              @pre_cfbsetkey@ and @pre_cfbsetiv@.                     \
163  */                                                                     \
164                                                                         \
165 void pre##_cfbinit(pre##_cfbctx *ctx,                                   \
166                    const void *key, size_t sz,                          \
167                    const void *iv)                                      \
168 {                                                                       \
169   static const octet zero[PRE##_BLKSZ] = { 0 };                         \
170                                                                         \
171   pre##_init(&ctx->ctx, key, sz);                                       \
172   pre##_cfbsetiv(ctx, iv ? iv : zero);                                  \
173 }                                                                       \
174                                                                         \
175 /* --- @pre_cfbencrypt@ --- *                                           \
176  *                                                                      \
177  * Arguments:   @pre_cfbctx *ctx@ = pointer to CFB context block        \
178  *              @const void *src@ = pointer to source data              \
179  *              @void *dest@ = pointer to destination data              \
180  *              @size_t sz@ = size of block to be encrypted             \
181  *                                                                      \
182  * Returns:     ---                                                     \
183  *                                                                      \
184  * Use:         Encrypts a block with a block cipher in CFB mode.  The  \
185  *              input block may be arbitrary in size.  CFB mode is not  \
186  *              sensitive to block boundaries.                          \
187  */                                                                     \
188                                                                         \
189 static const rsvr_policy pre##_cfbpolicy = { 0, PRE##_BLKSZ, PRE##_BLKSZ }; \
190                                                                         \
191 void pre##_cfbencrypt(pre##_cfbctx *ctx,                                \
192                       const void *src, void *dest,                      \
193                       size_t sz)                                        \
194 {                                                                       \
195   rsvr_plan plan;                                                       \
196   const octet *s = src;                                                 \
197   octet *d = dest, *p;                                                  \
198   uint32 t[PRE##_BLKSZ/4];                                              \
199   octet y;                                                              \
200                                                                         \
201   /* Construct a plan and prepare to follow through. */                 \
202   rsvr_mkplan(&plan, &pre##_cfbpolicy, ctx->off, sz);                   \
203   BLKC_LOAD(PRE, t, ctx->b);                                            \
204                                                                         \
205   /* Initial portion, fulfilled from the buffer.  If the chunk is small \
206    * enough, then this will be the only portion.  If the buffer is      \
207    * currently empty, then we must prepare it.                          \
208    */                                                                   \
209   if (plan.head) {                                                      \
210     if (!ctx->off) {                                                    \
211       pre##_eblk(&ctx->ctx, t, t);                                      \
212       BLKC_STORE(PRE, ctx->b, t);                                       \
213     }                                                                   \
214     p = ctx->b + ctx->off; ctx->off += plan.head;                       \
215     if (s) while (plan.head--) { y = *s++ ^ *p; *p++ = y; if (d) *d++ = y; } \
216     else if (d) { memcpy(d, p, plan.head); d += plan.head; }            \
217     BLKC_LOAD(PRE, t, ctx->b);                                          \
218   }                                                                     \
219                                                                         \
220   /* If the buffer is all used, then reset it ready for next time. */   \
221   ctx->off -= plan.from_rsvr;                                           \
222                                                                         \
223   /* Handle multiple whole blocks. */                                   \
224   if (!d) {                                                             \
225     if (!s) while (plan.from_input) {                                   \
226       pre##_eblk(&ctx->ctx, t, t);                                      \
227       plan.from_input -= PRE##_BLKSZ;                                   \
228     } else while (plan.from_input) {                                    \
229       pre##_eblk(&ctx->ctx, t, t);                                      \
230       BLKC_XLOAD(PRE, t, s); s += PRE##_BLKSZ;                          \
231       plan.from_input -= PRE##_BLKSZ;                                   \
232     }                                                                   \
233   } else {                                                              \
234     if (!s) while (plan.from_input) {                                   \
235       pre##_eblk(&ctx->ctx, t, t);                                      \
236       BLKC_STORE(PRE, d, t); d += PRE##_BLKSZ;                          \
237       plan.from_input -= PRE##_BLKSZ;                                   \
238     } else while (plan.from_input) {                                    \
239       pre##_eblk(&ctx->ctx, t, t);                                      \
240       BLKC_XLOAD(PRE, t, s); s += PRE##_BLKSZ;                          \
241       BLKC_STORE(PRE, d, t); d += PRE##_BLKSZ;                          \
242       plan.from_input -= PRE##_BLKSZ;                                   \
243     }                                                                   \
244   }                                                                     \
245                                                                         \
246   /* Final portion.  Note that the buffer must be empty if there is a   \
247    * tail, since otherwise the input data would have been part of the   \
248    * head portion instad. */                                            \
249   if (!plan.tail)                                                       \
250     BLKC_STORE(PRE, ctx->b, t);                                         \
251   else {                                                                \
252     pre##_eblk(&ctx->ctx, t, t);                                        \
253     BLKC_STORE(PRE, ctx->b, t);                                         \
254     p = ctx->b; ctx->off += plan.tail;                                  \
255     if (s) while (plan.tail--) { y = *s++ ^ *p; *p++ = y; if (d) *d++ = y; } \
256     else if (d) { memcpy(d, p, plan.tail); d += plan.tail; }            \
257   }                                                                     \
258 }                                                                       \
259                                                                         \
260 /* --- @pre_cfbdecrypt@ --- *                                           \
261  *                                                                      \
262  * Arguments:   @pre_cfbctx *ctx@ = pointer to CFB context block        \
263  *              @const void *src@ = pointer to source data              \
264  *              @void *dest@ = pointer to destination data              \
265  *              @size_t sz@ = size of block to be encrypted             \
266  *                                                                      \
267  * Returns:     ---                                                     \
268  *                                                                      \
269  * Use:         Decrypts a block with a block cipher in CFB mode.  The  \
270  *              input block may be arbitrary in size.  CFB mode is not  \
271  *              sensitive to block boundaries.                          \
272  */                                                                     \
273                                                                         \
274 void pre##_cfbdecrypt(pre##_cfbctx *ctx,                                \
275                       const void *src, void *dest,                      \
276                       size_t sz)                                        \
277 {                                                                       \
278   rsvr_plan plan;                                                       \
279   const octet *s = src;                                                 \
280   octet *d = dest, *p;                                                  \
281   uint32 t[PRE##_BLKSZ/4], u[PRE##_BLKSZ/4];                            \
282   octet y;                                                              \
283                                                                         \
284   /* Construct a plan and prepare to follow through. */                 \
285   rsvr_mkplan(&plan, &pre##_cfbpolicy, ctx->off, sz);                   \
286   BLKC_LOAD(PRE, t, ctx->b);                                            \
287                                                                         \
288   /* Initial portion, fulfilled from the buffer.  If the chunk is small \
289    * enough, then this will be the only portion.  If the buffer is      \
290    * currently empty, then we must prepare it.                          \
291    */                                                                   \
292   if (plan.head) {                                                      \
293     if (!ctx->off) {                                                    \
294       pre##_eblk(&ctx->ctx, t, t);                                      \
295       BLKC_STORE(PRE, ctx->b, t);                                       \
296     }                                                                   \
297     p = ctx->b + ctx->off;                                              \
298     ctx->off += plan.head;                                              \
299     while (plan.head--) { y = *s++; *d++ = y ^ *p; *p++ = y; }          \
300     BLKC_LOAD(PRE, t, ctx->b);                                          \
301   }                                                                     \
302                                                                         \
303   /* If the buffer is all used, then reset it ready for next time. */   \
304   ctx->off -= plan.from_rsvr;                                           \
305                                                                         \
306   /* Handle multiple whole blocks. */                                   \
307   while (plan.from_input) {                                             \
308     pre##_eblk(&ctx->ctx, t, t);                                        \
309     BLKC_LOAD(PRE, u, s); s += PRE##_BLKSZ;                             \
310     BLKC_XSTORE(PRE, d, t, u); d += PRE##_BLKSZ;                        \
311     BLKC_MOVE(PRE, t, u);                                               \
312     plan.from_input -= PRE##_BLKSZ;                                     \
313   }                                                                     \
314                                                                         \
315   /* Final portion.  Note that the buffer must be empty if there is a   \
316    * tail, since otherwise the input data would have been part of the   \
317    * head portion instad. */                                            \
318   if (!plan.tail)                                                       \
319     BLKC_STORE(PRE, ctx->b, t);                                         \
320   else {                                                                \
321     pre##_eblk(&ctx->ctx, t, t);                                        \
322     BLKC_STORE(PRE, ctx->b, t);                                         \
323     p = ctx->b;                                                         \
324     ctx->off += plan.tail;                                              \
325     while (plan.tail--) { y = *s++; *d++ = y ^ *p; *p++ = y; }          \
326   }                                                                     \
327 }                                                                       \
328                                                                         \
329 /* --- Generic cipher interface --- */                                  \
330                                                                         \
331 static const gcipher_ops gops;                                          \
332                                                                         \
333 typedef struct gctx {                                                   \
334   gcipher c;                                                            \
335   pre##_cfbctx k;                                                       \
336 } gctx;                                                                 \
337                                                                         \
338 static gcipher *ginit(const void *k, size_t sz)                         \
339 {                                                                       \
340   gctx *g = S_CREATE(gctx);                                             \
341   g->c.ops = &gops;                                                     \
342   pre##_cfbinit(&g->k, k, sz, 0);                                       \
343   return (&g->c);                                                       \
344 }                                                                       \
345                                                                         \
346 static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)     \
347   { gctx *g = (gctx *)c; pre##_cfbencrypt(&g->k, s, t, sz); }           \
348                                                                         \
349 static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz)     \
350   { gctx *g = (gctx *)c; pre##_cfbdecrypt(&g->k, s, t, sz); }           \
351                                                                         \
352 static void gdestroy(gcipher *c)                                        \
353   { gctx *g = (gctx *)c; BURN(*g); S_DESTROY(g); }                      \
354                                                                         \
355 static void gsetiv(gcipher *c, const void *iv)                          \
356   { gctx *g = (gctx *)c; pre##_cfbsetiv(&g->k, iv); }                   \
357                                                                         \
358 static void gbdry(gcipher *c)                                           \
359   { gctx *g = (gctx *)c; pre##_cfbbdry(&g->k); }                        \
360                                                                         \
361 static const gcipher_ops gops = {                                       \
362   &pre##_cfb,                                                           \
363   gencrypt, gdecrypt, gdestroy, gsetiv, gbdry                           \
364 };                                                                      \
365                                                                         \
366 const gccipher pre##_cfb = {                                            \
367   name "-cfb", pre##_keysz, PRE##_BLKSZ,                                \
368   ginit                                                                 \
369 };                                                                      \
370                                                                         \
371 CFB_TESTX(PRE, pre, name, fname)
372
373 /*----- Test rig ----------------------------------------------------------*/
374
375 #define CFB_TEST(PRE, pre) CFB_TESTX(PRE, pre, #pre, #pre)
376
377 #ifdef TEST_RIG
378
379 #include "modes-test.h"
380
381 /* --- @CFB_TEST@ --- *
382  *
383  * Arguments:   @PRE@, @pre@ = prefixes for block cipher definitions
384  *
385  * Use:         Standard test rig for CFB functions.
386  */
387
388 #define CFB_TESTX(PRE, pre, name, fname)                                \
389                                                                         \
390 static pre##_ctx key;                                                   \
391 static pre##_cfbctx ctx;                                                \
392                                                                         \
393 static void pre##_cfb_test_setup(const octet *k, size_t ksz)            \
394   { pre##_init(&key, k, ksz); pre##_cfbsetkey(&ctx, &key); }            \
395                                                                         \
396 static void pre##_cfb_test_reset(const octet *iv)                       \
397   { pre##_cfbsetiv(&ctx, iv); }                                         \
398                                                                         \
399 static void pre##_cfb_test_enc(const octet *s, octet *d, size_t sz)     \
400   { pre##_cfbencrypt(&ctx, s, d, sz); }                                 \
401                                                                         \
402 static void pre##_cfb_test_dec(const octet *s, octet *d, size_t sz)     \
403   { pre##_cfbdecrypt(&ctx, s, d, sz); }                                 \
404                                                                         \
405 int main(int argc, char *argv[])                                        \
406 {                                                                       \
407   return test_encmode(fname "-cfb", PRE##_KEYSZ, PRE##_BLKSZ, 1, 0,     \
408                       pre##_cfb_test_setup, pre##_cfb_test_reset,       \
409                       pre##_cfb_test_enc, pre##_cfb_test_dec,           \
410                       argc, argv);                                      \
411 }
412
413 #else
414 #  define CFB_TESTX(PRE, pre, name, fname)
415 #endif
416
417 /*----- That's all, folks -------------------------------------------------*/
418
419 #ifdef __cplusplus
420   }
421 #endif
422
423 #endif