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