chiark / gitweb /
Expunge revision histories in files.
[catacomb] / ecb-def.h
1 /* -*-c-*-
2  *
3  * $Id: ecb-def.h,v 1.3 2004/04/08 01:36:15 mdw Exp $
4  *
5  * Definitions electronic code book 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_ECB_DEF_H
31 #define CATACOMB_ECB_DEF_H
32
33 #ifdef __cplusplus
34   extern "C" {
35 #endif
36
37 /*----- Header files ------------------------------------------------------*/
38
39 #include <assert.h>
40 #include <string.h>
41
42 #include <mLib/bits.h>
43 #include <mLib/sub.h>
44
45 #ifndef CATACOMB_ARENA_H
46 #  include "arena.h"
47 #endif
48
49 #ifndef CATACOMB_BLKC_H
50 #  include "blkc.h"
51 #endif
52
53 #ifndef CATACOMB_GCIPHER_H
54 #  include "gcipher.h"
55 #endif
56
57 #ifndef CATACOMB_PARANOIA_H
58 #  include "paranoia.h"
59 #endif
60
61 /*----- Macros ------------------------------------------------------------*/
62
63 /* --- @ECB_DEF@ --- *
64  *
65  * Arguments:   @PRE@, @pre@ = prefixes for the underlying block cipher
66  *
67  * Use:         Creates an implementation for ECB stealing mode.
68  */
69
70 #define ECB_DEF(PRE, pre)                                               \
71                                                                         \
72 /* --- @pre_ecbsetkey@ --- *                                            \
73  *                                                                      \
74  * Arguments:   @pre_ecbctx *ctx@ = pointer to ECB context block        \
75  *              @const pre_ctx *k@ = pointer to cipher context          \
76  *                                                                      \
77  * Returns:     ---                                                     \
78  *                                                                      \
79  * Use:         Sets the ECB context to use a different cipher key.     \
80  */                                                                     \
81                                                                         \
82 void pre##_ecbsetkey(pre##_ecbctx *ctx, const pre##_ctx *k)             \
83 {                                                                       \
84   ctx->ctx = *k;                                                        \
85 }                                                                       \
86                                                                         \
87 /* --- @pre_ecbinit@ --- *                                              \
88  *                                                                      \
89  * Arguments:   @pre_ecbctx *ctx@ = pointer to cipher context           \
90  *              @const void *key@ = pointer to the key buffer           \
91  *              @size_t sz@ = size of the key                           \
92  *              @const void *iv@ = pointer to initialization vector     \
93  *                                                                      \
94  * Returns:     ---                                                     \
95  *                                                                      \
96  * Use:         Initializes an ECB context ready for use.  This is      \
97  *              equivalent to calls to @pre_init@ and @pre_setkey@.     \
98  */                                                                     \
99                                                                         \
100 void pre##_ecbinit(pre##_ecbctx *ctx,                                   \
101                      const void *key, size_t sz,                        \
102                      const void *iv)                                    \
103 {                                                                       \
104   pre##_init(&ctx->ctx, key, sz);                                       \
105 }                                                                       \
106                                                                         \
107 /* --- @pre_ecbencrypt@ --- *                                           \
108  *                                                                      \
109  * Arguments:   @pre_ecbctx *ctx@ = pointer to ECB context block        \
110  *              @const void *src@ = pointer to source data              \
111  *              @void *dest@ = pointer to destination data              \
112  *              @size_t sz@ = size of block to be encrypted             \
113  *                                                                      \
114  * Returns:     ---                                                     \
115  *                                                                      \
116  * Use:         Encrypts a block with a block cipher in ECB mode, with  \
117  *              ciphertext stealing and other clever tricks.            \
118  *              Essentially, data can be encrypted in arbitrary sized   \
119  *              chunks, although decryption must use the same chunks.   \
120  */                                                                     \
121                                                                         \
122 void pre##_ecbencrypt(pre##_ecbctx *ctx,                                \
123                         const void *src, void *dest,                    \
124                         size_t sz)                                      \
125 {                                                                       \
126   const octet *s = src;                                                 \
127   octet *d = dest;                                                      \
128                                                                         \
129   /* --- Empty blocks are trivial --- */                                \
130                                                                         \
131   if (!sz)                                                              \
132     return;                                                             \
133                                                                         \
134   /* --- Short blocks aren't allowed in ECB --- *                       \
135    *                                                                    \
136    * There's absolutely nothing secure I can do with them.              \
137    */                                                                   \
138                                                                         \
139   assert(((void)"ECB must have at least one whole block to work with",  \
140           sz >= PRE##_BLKSZ));                                          \
141                                                                         \
142   /* --- Do the main chunk of encryption --- *                          \
143    *                                                                    \
144    * This will do the whole lot if it's a whole number of blocks.  Just \
145    * give each block to the cipher in turn.  This is trivial.           \
146    * Hopefully...                                                       \
147    */                                                                   \
148                                                                         \
149   while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) {                  \
150     uint32 x[PRE##_BLKSZ / 4];                                          \
151     BLKC_LOAD(PRE, x, s);                                               \
152     pre##_eblk(&ctx->ctx, x, x);                                        \
153     BLKC_STORE(PRE, d, x);                                              \
154     s += PRE##_BLKSZ;                                                   \
155     d += PRE##_BLKSZ;                                                   \
156     sz -= PRE##_BLKSZ;                                                  \
157   }                                                                     \
158                                                                         \
159   /* --- Do the tail-end block and bit-left-over --- *                  \
160    *                                                                    \
161    * This isn't very efficient.  That shouldn't matter much.            \
162    */                                                                   \
163                                                                         \
164   if (sz) {                                                             \
165     uint32 x[PRE##_BLKSZ / 4];                                          \
166     octet b[PRE##_BLKSZ];                                               \
167     unsigned i;                                                         \
168                                                                         \
169     /* --- Let @sz@ be the size of the partial block --- */             \
170                                                                         \
171     sz -= PRE##_BLKSZ;                                                  \
172                                                                         \
173     /* --- First stage --- *                                            \
174      *                                                                  \
175      * Read in the current block, and encrypt it.  The first part of    \
176      * the result is the partial ciphertext block.  Don't write that    \
177      * out yet, because I've not read the partial plaintext block.      \
178      */                                                                 \
179                                                                         \
180     BLKC_LOAD(PRE, x, s);                                               \
181     pre##_eblk(&ctx->ctx, x, x);                                        \
182     BLKC_STORE(PRE, b, x);                                              \
183                                                                         \
184     /* --- Second stage --- *                                           \
185      *                                                                  \
186      * Now move in the partial plaintext block, writing out the         \
187      * ciphertext as I go.  Then encrypt, and write the complete        \
188      * ciphertext block.                                                \
189      */                                                                 \
190                                                                         \
191     s += PRE##_BLKSZ;                                                   \
192     d += PRE##_BLKSZ;                                                   \
193     for (i = 0; i < sz; i++) {                                          \
194       register octet y = b[i];                                          \
195       b[i] = s[i];                                                      \
196       d[i] = y;                                                         \
197     }                                                                   \
198     BLKC_LOAD(PRE, x, b);                                               \
199     pre##_eblk(&ctx->ctx, x, x);                                        \
200     BLKC_STORE(PRE, d - PRE##_BLKSZ, x);                                \
201   }                                                                     \
202                                                                         \
203   /* --- Done --- */                                                    \
204                                                                         \
205   return;                                                               \
206 }                                                                       \
207                                                                         \
208 /* --- @pre_ecbdecrypt@ --- *                                           \
209  *                                                                      \
210  * Arguments:   @pre_ecbctx *ctx@ = pointer to ECB context block        \
211  *              @const void *src@ = pointer to source data              \
212  *              @void *dest@ = pointer to destination data              \
213  *              @size_t sz@ = size of block to be encrypted             \
214  *                                                                      \
215  * Returns:     ---                                                     \
216  *                                                                      \
217  * Use:         Decrypts a block with a block cipher in ECB mode, with  \
218  *              ciphertext stealing and other clever tricks.            \
219  *              Essentially, data can be encrypted in arbitrary sized   \
220  *              chunks, although decryption must use the same chunks.   \
221  */                                                                     \
222                                                                         \
223 void pre##_ecbdecrypt(pre##_ecbctx *ctx,                                \
224                         const void *src, void *dest,                    \
225                         size_t sz)                                      \
226 {                                                                       \
227   const octet *s = src;                                                 \
228   octet *d = dest;                                                      \
229                                                                         \
230   /* --- Empty blocks are trivial --- */                                \
231                                                                         \
232   if (!sz)                                                              \
233     return;                                                             \
234                                                                         \
235   /* --- Short blocks aren't allowed in ECB --- *                       \
236    *                                                                    \
237    * There's absolutely nothing secure I can do with them.              \
238    */                                                                   \
239                                                                         \
240   assert(((void)"ECB must have at least one whole block to work with",  \
241           sz >= PRE##_BLKSZ));                                          \
242                                                                         \
243   /* --- Do the main chunk of decryption --- *                          \
244    *                                                                    \
245    * This will do the whole lot if it's a whole number of blocks.       \
246    * Each block is just handed to the block cipher in turn.             \
247    */                                                                   \
248                                                                         \
249   while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) {                  \
250     uint32 x[PRE##_BLKSZ / 4];                                          \
251     BLKC_LOAD(PRE, x, s);                                               \
252     pre##_dblk(&ctx->ctx, x, x);                                        \
253     BLKC_STORE(PRE, d, x);                                              \
254     s += PRE##_BLKSZ;                                                   \
255     d += PRE##_BLKSZ;                                                   \
256     sz -= PRE##_BLKSZ;                                                  \
257   }                                                                     \
258                                                                         \
259   /* --- Do the tail-end block and bit-left-over --- *                  \
260    *                                                                    \
261    * This isn't very efficient.  That shouldn't matter much.            \
262    */                                                                   \
263                                                                         \
264   if (sz) {                                                             \
265     uint32 x[PRE##_BLKSZ / 4];                                          \
266     octet b[PRE##_BLKSZ];                                               \
267     unsigned i;                                                         \
268                                                                         \
269     /* --- Let @sz@ be the size of the partial block --- */             \
270                                                                         \
271     sz -= PRE##_BLKSZ;                                                  \
272                                                                         \
273     /* --- First stage --- *                                            \
274      *                                                                  \
275      * Take the complete ciphertext block, and decrypt it.  This block  \
276      * is carried over for the next encryption operation.               \
277      */                                                                 \
278                                                                         \
279     BLKC_LOAD(PRE, x, s);                                               \
280     pre##_dblk(&ctx->ctx, x, x);                                        \
281     BLKC_STORE(PRE, b, x);                                              \
282                                                                         \
283     /* --- Second stage --- *                                           \
284      *                                                                  \
285      * The first few bytes are the partial plaintext block.  Write that \
286      * and replace with the partial ciphertext block.  Then decrypt     \
287      * what's left as the complete plaintext.                           \
288      */                                                                 \
289                                                                         \
290     s += PRE##_BLKSZ;                                                   \
291     d += PRE##_BLKSZ;                                                   \
292     for (i = 0; i < sz; i++) {                                          \
293       register octet y = s[i];                                          \
294       d[i] = b[i];                                                      \
295       b[i] = y;                                                         \
296     }                                                                   \
297     BLKC_LOAD(PRE, x, b);                                               \
298     pre##_dblk(&ctx->ctx, x, x);                                        \
299     BLKC_STORE(PRE, d - PRE##_BLKSZ, x);                                \
300   }                                                                     \
301                                                                         \
302   /* --- Done --- */                                                    \
303                                                                         \
304   return;                                                               \
305 }                                                                       \
306                                                                         \
307 /* --- Generic cipher interface --- */                                  \
308                                                                         \
309 static const gcipher_ops gops;                                          \
310                                                                         \
311 typedef struct gctx {                                                   \
312   gcipher c;                                                            \
313   pre##_ecbctx k;                                                       \
314 } gctx;                                                                 \
315                                                                         \
316 static gcipher *ginit(const void *k, size_t sz)                         \
317 {                                                                       \
318   gctx *g = S_CREATE(gctx);                                             \
319   g->c.ops = &gops;                                                     \
320   pre##_ecbinit(&g->k, k, sz, 0);                                       \
321   return (&g->c);                                                       \
322 }                                                                       \
323                                                                         \
324 static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)     \
325 {                                                                       \
326   gctx *g = (gctx *)c;                                                  \
327   pre##_ecbencrypt(&g->k, s, t, sz);                                    \
328 }                                                                       \
329                                                                         \
330 static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz)     \
331 {                                                                       \
332   gctx *g = (gctx *)c;                                                  \
333   pre##_ecbdecrypt(&g->k, s, t, sz);                                    \
334 }                                                                       \
335                                                                         \
336 static void gdestroy(gcipher *c)                                        \
337 {                                                                       \
338   gctx *g = (gctx *)c;                                                  \
339   BURN(*g);                                                             \
340   S_DESTROY(g);                                                         \
341 }                                                                       \
342                                                                         \
343 static const gcipher_ops gops = {                                       \
344   &pre##_ecb,                                                           \
345   gencrypt, gdecrypt, gdestroy, 0, 0                                    \
346 };                                                                      \
347                                                                         \
348 const gccipher pre##_ecb = {                                            \
349   #pre "-ecb", pre##_keysz, PRE##_BLKSZ,                                \
350   ginit                                                                 \
351 };                                                                      \
352                                                                         \
353 ECB_TEST(PRE, pre)
354
355 /*----- Test rig ----------------------------------------------------------*/
356
357 #ifdef TEST_RIG
358
359 #include <stdio.h>
360
361 #include "daftstory.h"
362
363 /* --- @ECB_TEST@ --- *
364  *
365  * Arguments:   @PRE@, @pre@ = prefixes for block cipher definitions
366  *
367  * Use:         Standard test rig for ECB functions.
368  */
369
370 #define ECB_TEST(PRE, pre)                                              \
371                                                                         \
372 /* --- Initial plaintext for the test --- */                            \
373                                                                         \
374 static const octet text[] = TEXT;                                       \
375                                                                         \
376 /* --- Key and IV to use --- */                                         \
377                                                                         \
378 static const octet key[] = KEY;                                         \
379 static const octet iv[] = IV;                                           \
380                                                                         \
381 /* --- Buffers for encryption and decryption output --- */              \
382                                                                         \
383 static octet ct[sizeof(text)];                                          \
384 static octet pt[sizeof(text)];                                          \
385                                                                         \
386 static void hexdump(const octet *p, size_t sz)                          \
387 {                                                                       \
388   const octet *q = p + sz;                                              \
389   for (sz = 0; p < q; p++, sz++) {                                      \
390     printf("%02x", *p);                                                 \
391     if ((sz + 1) % PRE##_BLKSZ == 0)                                    \
392       putchar(':');                                                     \
393   }                                                                     \
394 }                                                                       \
395                                                                         \
396 int main(void)                                                          \
397 {                                                                       \
398   size_t sz = 0, rest;                                                  \
399   pre##_ecbctx ctx;                                                     \
400   int status = 0;                                                       \
401   int done = 0;                                                         \
402                                                                         \
403   size_t keysz = PRE##_KEYSZ ?                                          \
404     PRE##_KEYSZ : strlen((const char *)key);                            \
405                                                                         \
406   fputs(#pre "-ecb: ", stdout);                                         \
407                                                                         \
408   pre##_ecbinit(&ctx, key, keysz, iv);                                  \
409                                                                         \
410   while (sz <= sizeof(text)) {                                          \
411     rest = sizeof(text) - sz;                                           \
412     if ((sz != 0 && sz < PRE##_BLKSZ) ||                                \
413         (rest != 0 && rest < PRE##_BLKSZ))                              \
414       goto next;                                                        \
415     memcpy(ct, text, sizeof(text));                                     \
416     pre##_ecbencrypt(&ctx, ct, ct, sz);                                 \
417     pre##_ecbencrypt(&ctx, ct + sz, ct + sz, rest);                     \
418     memcpy(pt, ct, sizeof(text));                                       \
419     pre##_ecbdecrypt(&ctx, pt, pt, sz);                                 \
420     pre##_ecbdecrypt(&ctx, pt + sz, pt + sz, rest);                     \
421     if (memcmp(pt, text, sizeof(text)) == 0) {                          \
422       done++;                                                           \
423       if (sizeof(text) < 40 || done % 8 == 0)                           \
424         fputc('.', stdout);                                             \
425       if (done % 480 == 0)                                              \
426         fputs("\n\t", stdout);                                          \
427       fflush(stdout);                                                   \
428     } else {                                                            \
429       printf("\nError (sz = %lu)\n", (unsigned long)sz);                \
430       status = 1;                                                       \
431       printf("\tplaintext      = "); hexdump(text, sz);                 \
432         printf(", "); hexdump(text + sz, rest);                         \
433         fputc('\n', stdout);                                            \
434       printf("\tciphertext     = "); hexdump(ct, sz);                   \
435         printf(", "); hexdump(ct + sz, rest);                           \
436         fputc('\n', stdout);                                            \
437       printf("\trecovered text = "); hexdump(pt, sz);                   \
438         printf(", "); hexdump(pt + sz, rest);                           \
439         fputc('\n', stdout);                                            \
440       fputc('\n', stdout);                                              \
441     }                                                                   \
442   next:                                                                 \
443     if (sz < 63)                                                        \
444       sz++;                                                             \
445     else                                                                \
446       sz += 9;                                                          \
447   }                                                                     \
448                                                                         \
449   fputs(status ? " failed\n" : " ok\n", stdout);                        \
450   return (status);                                                      \
451 }
452
453 #else
454 #  define ECB_TEST(PRE, pre)
455 #endif
456
457 /*----- That's all, folks -------------------------------------------------*/
458
459 #ifdef __cplusplus
460   }
461 #endif
462
463 #endif