chiark / gitweb /
base/asm-common.h: Define `WORDSZ' appropriately for x86ish platforms.
[catacomb] / symm / cbc-def.h
1 /* -*-c-*-
2  *
3  * Definitions for cipher block chaining 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_CBC_DEF_H
29 #define CATACOMB_CBC_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 /*----- Macros ------------------------------------------------------------*/
59
60 /* --- @CBC_DEF@ --- *
61  *
62  * Arguments:   @PRE@, @pre@ = prefixes for the underlying block cipher
63  *
64  * Use:         Creates an implementation for CBC stealing mode.
65  */
66
67 #define CBC_DEF(PRE, pre)                                               \
68                                                                         \
69 /* --- @pre_cbcgetiv@ --- *                                             \
70  *                                                                      \
71  * Arguments:   @const pre_cbcctx *ctx@ = pointer to CBC context block  \
72  *              @void *iv@ = pointer to output data block               \
73  *                                                                      \
74  * Returns:     ---                                                     \
75  *                                                                      \
76  * Use:         Reads the currently set IV.  Reading and setting an IV  \
77  *              is transparent to the CBC encryption or decryption      \
78  *              process.                                                \
79  */                                                                     \
80                                                                         \
81 void pre##_cbcgetiv(const pre##_cbcctx *ctx, void *iv)                  \
82 {                                                                       \
83   BLKC_STORE(PRE, iv, ctx->iv);                                         \
84 }                                                                       \
85                                                                         \
86 /* --- @pre_cbcsetiv@ --- *                                             \
87  *                                                                      \
88  * Arguments:   @pre_cbcctx *ctx@ = pointer to CBC context block        \
89  *              @cnost void *iv@ = pointer to IV to set                 \
90  *                                                                      \
91  * Returns:     ---                                                     \
92  *                                                                      \
93  * Use:         Sets the IV to use for subsequent encryption.           \
94  */                                                                     \
95                                                                         \
96 void pre##_cbcsetiv(pre##_cbcctx *ctx, const void *iv)                  \
97 {                                                                       \
98   BLKC_LOAD(PRE, ctx->iv, iv);                                          \
99 }                                                                       \
100                                                                         \
101 /* --- @pre_cbcsetkey@ --- *                                            \
102  *                                                                      \
103  * Arguments:   @pre_cbcctx *ctx@ = pointer to CBC context block        \
104  *              @const pre_ctx *k@ = pointer to cipher context          \
105  *                                                                      \
106  * Returns:     ---                                                     \
107  *                                                                      \
108  * Use:         Sets the CBC context to use a different cipher key.     \
109  */                                                                     \
110                                                                         \
111 void pre##_cbcsetkey(pre##_cbcctx *ctx, const pre##_ctx *k)             \
112 {                                                                       \
113   ctx->ctx = *k;                                                        \
114 }                                                                       \
115                                                                         \
116 /* --- @pre_cbcinit@ --- *                                              \
117  *                                                                      \
118  * Arguments:   @pre_cbcctx *ctx@ = pointer to cipher context           \
119  *              @const void *key@ = pointer to the key buffer           \
120  *              @size_t sz@ = size of the key                           \
121  *              @const void *iv@ = pointer to initialization vector     \
122  *                                                                      \
123  * Returns:     ---                                                     \
124  *                                                                      \
125  * Use:         Initializes a CBC context ready for use.  The @iv@      \
126  *              argument may be passed as a null pointer to set a zero  \
127  *              IV.  Apart from that, this call is equivalent to calls  \
128  *              to @pre_init@, @pre_cbcsetkey@ and @pre_cbcsetiv@.      \
129  */                                                                     \
130                                                                         \
131 void pre##_cbcinit(pre##_cbcctx *ctx,                                   \
132                      const void *key, size_t sz,                        \
133                      const void *iv)                                    \
134 {                                                                       \
135   static const octet zero[PRE##_BLKSZ] = { 0 };                         \
136   pre##_init(&ctx->ctx, key, sz);                                       \
137   BLKC_LOAD(PRE, ctx->iv, iv ? iv : zero);                              \
138 }                                                                       \
139                                                                         \
140 /* --- @pre_cbcencrypt@ --- *                                           \
141  *                                                                      \
142  * Arguments:   @pre_cbcctx *ctx@ = pointer to CBC context block        \
143  *              @const void *src@ = pointer to source data              \
144  *              @void *dest@ = pointer to destination data              \
145  *              @size_t sz@ = size of block to be encrypted             \
146  *                                                                      \
147  * Returns:     ---                                                     \
148  *                                                                      \
149  * Use:         Encrypts a block with a block cipher in CBC mode, with  \
150  *              ciphertext stealing and other clever tricks.            \
151  *              Essentially, data can be encrypted in arbitrary sized   \
152  *              chunks, although decryption must use the same chunks.   \
153  */                                                                     \
154                                                                         \
155 void pre##_cbcencrypt(pre##_cbcctx *ctx,                                \
156                         const void *src, void *dest,                    \
157                         size_t sz)                                      \
158 {                                                                       \
159   const octet *s = src;                                                 \
160   octet *d = dest;                                                      \
161                                                                         \
162   /* --- Empty blocks are trivial --- */                                \
163                                                                         \
164   if (!sz)                                                              \
165     return;                                                             \
166                                                                         \
167   /* --- Extra magical case for a short block --- *                     \
168    *                                                                    \
169    * Encrypt the IV, then exclusive-or the plaintext with the octets    \
170    * of the encrypted IV, shifting ciphertext octets in instead.  This  \
171    * basically switches over to CFB.                                    \
172    */                                                                   \
173                                                                         \
174   if (sz < PRE##_BLKSZ) {                                               \
175     octet b[PRE##_BLKSZ];                                               \
176     unsigned i;                                                         \
177                                                                         \
178     pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv);                            \
179     BLKC_STORE(PRE, b, ctx->iv);                                        \
180     if (d) {                                                            \
181       for (i = 0; i < sz; i++)                                          \
182         d[i] = b[i] ^ (s ? s[i] : 0);                                   \
183     }                                                                   \
184     memmove(b, b + sz, PRE##_BLKSZ - sz);                               \
185     memcpy(b + PRE##_BLKSZ - sz, d, sz);                                \
186     BLKC_LOAD(PRE, ctx->iv, b);                                         \
187     return;                                                             \
188   }                                                                     \
189                                                                         \
190   /* --- Do the main chunk of encryption --- *                          \
191    *                                                                    \
192    * This will do the whole lot if it's a whole number of blocks.  For  \
193    * each block, XOR it with the previous ciphertext in @iv@, encrypt,  \
194    * and keep a copy of the ciphertext for the next block.              \
195    */                                                                   \
196                                                                         \
197   while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) {                  \
198     if (s) {                                                            \
199       BLKC_XLOAD(PRE, ctx->iv, s);                                      \
200       s += PRE##_BLKSZ;                                                 \
201     }                                                                   \
202     pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv);                            \
203     if (d) {                                                            \
204       BLKC_STORE(PRE, d, ctx->iv);                                      \
205       d += PRE##_BLKSZ;                                                 \
206     }                                                                   \
207     sz -= PRE##_BLKSZ;                                                  \
208   }                                                                     \
209                                                                         \
210   /* --- Do the tail-end block and bit-left-over --- *                  \
211    *                                                                    \
212    * This isn't very efficient.  That shouldn't matter much.            \
213    */                                                                   \
214                                                                         \
215   if (sz) {                                                             \
216     octet b[PRE##_BLKSZ];                                               \
217     unsigned i;                                                         \
218                                                                         \
219     /* --- Let @sz@ be the size of the partial block --- */             \
220                                                                         \
221     sz -= PRE##_BLKSZ;                                                  \
222                                                                         \
223     /* --- First stage --- *                                            \
224      *                                                                  \
225      * XOR the complete block with the current IV, and encrypt it.  The \
226      * first part of the result is the partial ciphertext block.  Don't \
227      * write that out yet, because I've not read the partial plaintext  \
228      * block.                                                           \
229      */                                                                 \
230                                                                         \
231     if (s) BLKC_XLOAD(PRE, ctx->iv, s);                                 \
232     pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv);                            \
233     BLKC_STORE(PRE, b, ctx->iv);                                        \
234                                                                         \
235     /* --- Second stage --- *                                           \
236      *                                                                  \
237      * Now XOR in the partial plaintext block, writing out the          \
238      * ciphertext as I go.  Then encrypt, and write the complete        \
239      * ciphertext block.                                                \
240      */                                                                 \
241                                                                         \
242     if (s) s += PRE##_BLKSZ;                                            \
243     if (d) d += PRE##_BLKSZ;                                            \
244     for (i = 0; i < sz; i++) {                                          \
245       register octet x = b[i];                                          \
246       if (s) b[i] ^= s[i];                                              \
247       if (d) d[i] = x;                                                  \
248     }                                                                   \
249     BLKC_LOAD(PRE, ctx->iv, b);                                         \
250     pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv);                            \
251     if (d) BLKC_STORE(PRE, d - PRE##_BLKSZ, ctx->iv);                   \
252   }                                                                     \
253                                                                         \
254   /* --- Done --- */                                                    \
255                                                                         \
256   return;                                                               \
257 }                                                                       \
258                                                                         \
259 /* --- @pre_cbcdecrypt@ --- *                                           \
260  *                                                                      \
261  * Arguments:   @pre_cbcctx *ctx@ = pointer to CBC context block        \
262  *              @const void *src@ = pointer to source data              \
263  *              @void *dest@ = pointer to destination data              \
264  *              @size_t sz@ = size of block to be encrypted             \
265  *                                                                      \
266  * Returns:     ---                                                     \
267  *                                                                      \
268  * Use:         Decrypts a block with a block cipher in CBC mode, with  \
269  *              ciphertext stealing and other clever tricks.            \
270  *              Essentially, data can be encrypted in arbitrary sized   \
271  *              chunks, although decryption must use the same chunks.   \
272  */                                                                     \
273                                                                         \
274 void pre##_cbcdecrypt(pre##_cbcctx *ctx,                                \
275                         const void *src, void *dest,                    \
276                         size_t sz)                                      \
277 {                                                                       \
278   const octet *s = src;                                                 \
279   octet *d = dest;                                                      \
280                                                                         \
281   /* --- Empty blocks are trivial --- */                                \
282                                                                         \
283   if (!sz)                                                              \
284     return;                                                             \
285                                                                         \
286   /* --- Extra magical case for a short block --- *                     \
287    *                                                                    \
288    * Encrypt the IV, then exclusive-or the ciphertext with the octets   \
289    * of the encrypted IV, shifting ciphertext octets in instead.  This  \
290    * basically switches over to CFB.                                    \
291    */                                                                   \
292                                                                         \
293   if (sz < PRE##_BLKSZ) {                                               \
294     octet b[PRE##_BLKSZ], c[PRE##_BLKSZ];                               \
295     unsigned i;                                                         \
296                                                                         \
297     pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv);                            \
298     BLKC_STORE(PRE, b, ctx->iv);                                        \
299     for (i = 0; i < sz; i++) {                                          \
300       register octet x = s[i];                                          \
301       d[i] = b[i] ^ x;                                                  \
302       c[i] = x;                                                         \
303     }                                                                   \
304     memmove(b, b + sz, PRE##_BLKSZ - sz);                               \
305     memcpy(b + PRE##_BLKSZ - sz, c, sz);                                \
306     BLKC_LOAD(PRE, ctx->iv, b);                                         \
307     return;                                                             \
308   }                                                                     \
309                                                                         \
310   /* --- Do the main chunk of decryption --- *                          \
311    *                                                                    \
312    * This will do the whole lot if it's a whole number of blocks.  For  \
313    * each block, decrypt, XOR it with the previous ciphertext in @iv@,  \
314    * and keep a copy of the ciphertext for the next block.              \
315    */                                                                   \
316                                                                         \
317   while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) {                  \
318     uint32 b[PRE##_BLKSZ / 4], niv[PRE##_BLKSZ / 4];                    \
319     BLKC_LOAD(PRE, niv, s);                                             \
320     pre##_dblk(&ctx->ctx, niv, b);                                      \
321     BLKC_XSTORE(PRE, d, b, ctx->iv);                                    \
322     BLKC_MOVE(PRE, ctx->iv, niv);                                       \
323     s += PRE##_BLKSZ;                                                   \
324     d += PRE##_BLKSZ;                                                   \
325     sz -= PRE##_BLKSZ;                                                  \
326   }                                                                     \
327                                                                         \
328   /* --- Do the tail-end block and bit-left-over --- *                  \
329    *                                                                    \
330    * This isn't very efficient.  That shouldn't matter much.            \
331    */                                                                   \
332                                                                         \
333   if (sz) {                                                             \
334     octet b[PRE##_BLKSZ];                                               \
335     uint32 bk[PRE##_BLKSZ / 4], niv[PRE##_BLKSZ / 4];                   \
336     unsigned i;                                                         \
337                                                                         \
338     /* --- Let @sz@ be the size of the partial block --- */             \
339                                                                         \
340     sz -= PRE##_BLKSZ;                                                  \
341                                                                         \
342     /* --- First stage --- *                                            \
343      *                                                                  \
344      * Take the complete ciphertext block, and decrypt it.  This block  \
345      * is carried over for the next encryption operation.               \
346      */                                                                 \
347                                                                         \
348     BLKC_LOAD(PRE, niv, s);                                             \
349     pre##_dblk(&ctx->ctx, niv, bk);                                     \
350                                                                         \
351     /* --- Second stage --- *                                           \
352      *                                                                  \
353      * XORing the first few bytes of this with the partial ciphertext   \
354      * block recovers the partial plaintext block.  At the same time,   \
355      * write the partial ciphertext block's contents in ready for stage \
356      * three.                                                           \
357      */                                                                 \
358                                                                         \
359     BLKC_STORE(PRE, b, bk);                                             \
360     s += PRE##_BLKSZ;                                                   \
361     d += PRE##_BLKSZ;                                                   \
362     for (i = 0; i < sz; i++) {                                          \
363       register octet x = s[i];                                          \
364       d[i] = b[i] ^ x;                                                  \
365       b[i] = x;                                                         \
366     }                                                                   \
367                                                                         \
368     /* --- Third stage --- *                                            \
369      *                                                                  \
370      * Decrypt the block we've got left, and XOR with the initial IV to \
371      * recover the complete plaintext block.                            \
372      */                                                                 \
373                                                                         \
374     BLKC_LOAD(PRE, bk, b);                                              \
375     pre##_dblk(&ctx->ctx, bk, bk);                                      \
376     BLKC_XSTORE(PRE, d - PRE##_BLKSZ, bk, ctx->iv);                     \
377     BLKC_MOVE(PRE, ctx->iv, niv);                                       \
378   }                                                                     \
379                                                                         \
380   /* --- Done --- */                                                    \
381                                                                         \
382   return;                                                               \
383 }                                                                       \
384                                                                         \
385 /* --- Generic cipher interface --- */                                  \
386                                                                         \
387 static const gcipher_ops gops;                                          \
388                                                                         \
389 typedef struct gctx {                                                   \
390   gcipher c;                                                            \
391   pre##_cbcctx k;                                                       \
392 } gctx;                                                                 \
393                                                                         \
394 static gcipher *ginit(const void *k, size_t sz)                         \
395 {                                                                       \
396   gctx *g = S_CREATE(gctx);                                             \
397   g->c.ops = &gops;                                                     \
398   pre##_cbcinit(&g->k, k, sz, 0);                                       \
399   return (&g->c);                                                       \
400 }                                                                       \
401                                                                         \
402 static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)     \
403 {                                                                       \
404   gctx *g = (gctx *)c;                                                  \
405   pre##_cbcencrypt(&g->k, s, t, sz);                                    \
406 }                                                                       \
407                                                                         \
408 static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz)     \
409 {                                                                       \
410   gctx *g = (gctx *)c;                                                  \
411   pre##_cbcdecrypt(&g->k, s, t, sz);                                    \
412 }                                                                       \
413                                                                         \
414 static void gdestroy(gcipher *c)                                        \
415 {                                                                       \
416   gctx *g = (gctx *)c;                                                  \
417   BURN(*g);                                                             \
418   S_DESTROY(g);                                                         \
419 }                                                                       \
420                                                                         \
421 static void gsetiv(gcipher *c, const void *iv)                          \
422 {                                                                       \
423   gctx *g = (gctx *)c;                                                  \
424   pre##_cbcsetiv(&g->k, iv);                                            \
425 }                                                                       \
426                                                                         \
427 static const gcipher_ops gops = {                                       \
428   &pre##_cbc,                                                           \
429   gencrypt, gdecrypt, gdestroy, gsetiv, 0                               \
430 };                                                                      \
431                                                                         \
432 const gccipher pre##_cbc = {                                            \
433   #pre "-cbc", pre##_keysz, PRE##_BLKSZ,                                \
434   ginit                                                                 \
435 };                                                                      \
436                                                                         \
437 CBC_TEST(PRE, pre)
438
439 /*----- Test rig ----------------------------------------------------------*/
440
441 #ifdef TEST_RIG
442
443 #include <stdio.h>
444
445 #include "daftstory.h"
446
447 /* --- @CBC_TEST@ --- *
448  *
449  * Arguments:   @PRE@, @pre@ = prefixes for block cipher definitions
450  *
451  * Use:         Standard test rig for CBC functions.
452  */
453
454 #define CBC_TEST(PRE, pre)                                              \
455                                                                         \
456 /* --- Initial plaintext for the test --- */                            \
457                                                                         \
458 static const octet text[] = TEXT;                                       \
459                                                                         \
460 /* --- Key and IV to use --- */                                         \
461                                                                         \
462 static const octet key[] = KEY;                                         \
463 static const octet iv[] = IV;                                           \
464                                                                         \
465 /* --- Buffers for encryption and decryption output --- */              \
466                                                                         \
467 static octet ct[sizeof(text)];                                          \
468 static octet pt[sizeof(text)];                                          \
469                                                                         \
470 static void hexdump(const octet *p, size_t sz, size_t off)              \
471 {                                                                       \
472   const octet *q = p + sz;                                              \
473   for (sz = 0; p < q; p++, sz++) {                                      \
474     printf("%02x", *p);                                                 \
475     if ((off + sz + 1) % PRE##_BLKSZ == 0)                              \
476       putchar(':');                                                     \
477   }                                                                     \
478 }                                                                       \
479                                                                         \
480 int main(void)                                                          \
481 {                                                                       \
482   size_t sz = 0, rest;                                                  \
483   pre##_cbcctx ctx;                                                     \
484   pre##_ctx k;                                                          \
485   int status = 0;                                                       \
486   int done = 0;                                                         \
487                                                                         \
488   size_t keysz = PRE##_KEYSZ ?                                          \
489     PRE##_KEYSZ : strlen((const char *)key);                            \
490                                                                         \
491   fputs(#pre "-cbc: ", stdout);                                         \
492                                                                         \
493   pre##_init(&k, key, keysz);                                           \
494   pre##_cbcsetkey(&ctx, &k);                                            \
495                                                                         \
496   while (sz <= sizeof(text)) {                                          \
497     rest = sizeof(text) - sz;                                           \
498     memcpy(ct, text, sizeof(text));                                     \
499     pre##_cbcsetiv(&ctx, iv);                                           \
500     pre##_cbcencrypt(&ctx, ct, ct, sz);                                 \
501     pre##_cbcencrypt(&ctx, ct + sz, ct + sz, rest);                     \
502     memcpy(pt, ct, sizeof(text));                                       \
503     pre##_cbcsetiv(&ctx, iv);                                           \
504     pre##_cbcdecrypt(&ctx, pt, pt, sz);                                 \
505     pre##_cbcdecrypt(&ctx, pt + sz, pt + sz, rest);                     \
506     if (memcmp(pt, text, sizeof(text)) == 0) {                          \
507       done++;                                                           \
508       if (sizeof(text) < 40 || done % 8 == 0)                           \
509         fputc('.', stdout);                                             \
510       if (done % 480 == 0)                                              \
511         fputs("\n\t", stdout);                                          \
512       fflush(stdout);                                                   \
513     } else {                                                            \
514       printf("\nError (sz = %lu)\n", (unsigned long)sz);                \
515       status = 1;                                                       \
516       printf("\tplaintext      = "); hexdump(text, sz, 0);              \
517         printf(", "); hexdump(text + sz, rest, sz);                     \
518         fputc('\n', stdout);                                            \
519       printf("\tciphertext     = "); hexdump(ct, sz, 0);                \
520         printf(", "); hexdump(ct + sz, rest, sz);                       \
521         fputc('\n', stdout);                                            \
522       printf("\trecovered text = "); hexdump(pt, sz, 0);                \
523         printf(", "); hexdump(pt + sz, rest, sz);                       \
524         fputc('\n', stdout);                                            \
525       fputc('\n', stdout);                                              \
526     }                                                                   \
527     if (sz < 63)                                                        \
528       sz++;                                                             \
529     else                                                                \
530       sz += 9;                                                          \
531   }                                                                     \
532                                                                         \
533   fputs(status ? " failed\n" : " ok\n", stdout);                        \
534   return (status);                                                      \
535 }
536
537 #else
538 #  define CBC_TEST(PRE, pre)
539 #endif
540
541 /*----- That's all, folks -------------------------------------------------*/
542
543 #ifdef __cplusplus
544   }
545 #endif
546
547 #endif