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