chiark / gitweb /
Fix various assumptions about mpw sizes.
[catacomb] / ecb-def.h
1 /* -*-c-*-
2  *
3  * $Id: ecb-def.h,v 1.4 2004/04/17 09:58:37 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     if (!s)                                                             \
152       BLKC_ZERO(PRE, x);                                                \
153     else {                                                              \
154       BLKC_LOAD(PRE, x, s);                                             \
155       s += PRE##_BLKSZ;                                                 \
156     }                                                                   \
157     pre##_eblk(&ctx->ctx, x, x);                                        \
158     if (d) {                                                            \
159       BLKC_STORE(PRE, d, x);                                            \
160       d += PRE##_BLKSZ;                                                 \
161     }                                                                   \
162     sz -= PRE##_BLKSZ;                                                  \
163   }                                                                     \
164                                                                         \
165   /* --- Do the tail-end block and bit-left-over --- *                  \
166    *                                                                    \
167    * This isn't very efficient.  That shouldn't matter much.            \
168    */                                                                   \
169                                                                         \
170   if (sz) {                                                             \
171     uint32 x[PRE##_BLKSZ / 4];                                          \
172     octet b[PRE##_BLKSZ];                                               \
173     unsigned i;                                                         \
174                                                                         \
175     /* --- Let @sz@ be the size of the partial block --- */             \
176                                                                         \
177     sz -= PRE##_BLKSZ;                                                  \
178                                                                         \
179     /* --- First stage --- *                                            \
180      *                                                                  \
181      * Read in the current block, and encrypt it.  The first part of    \
182      * the result is the partial ciphertext block.  Don't write that    \
183      * out yet, because I've not read the partial plaintext block.      \
184      */                                                                 \
185                                                                         \
186     if (!s)                                                             \
187       BLKC_ZERO(PRE, x);                                                \
188     else {                                                              \
189       BLKC_LOAD(PRE, x, s);                                             \
190       s += PRE##_BLKSZ;                                                 \
191     }                                                                   \
192     pre##_eblk(&ctx->ctx, x, x);                                        \
193     BLKC_STORE(PRE, b, x);                                              \
194                                                                         \
195     /* --- Second stage --- *                                           \
196      *                                                                  \
197      * Now move in the partial plaintext block, writing out the         \
198      * ciphertext as I go.  Then encrypt, and write the complete        \
199      * ciphertext block.                                                \
200      */                                                                 \
201                                                                         \
202     if (d) d += PRE##_BLKSZ;                                            \
203     for (i = 0; i < sz; i++) {                                          \
204       register octet y = b[i];                                          \
205       b[i] = s[i];                                                      \
206       if (d) d[i] = y;                                                  \
207     }                                                                   \
208     BLKC_LOAD(PRE, x, b);                                               \
209     pre##_eblk(&ctx->ctx, x, x);                                        \
210     if (d) BLKC_STORE(PRE, d - PRE##_BLKSZ, x);                         \
211   }                                                                     \
212                                                                         \
213   /* --- Done --- */                                                    \
214                                                                         \
215   return;                                                               \
216 }                                                                       \
217                                                                         \
218 /* --- @pre_ecbdecrypt@ --- *                                           \
219  *                                                                      \
220  * Arguments:   @pre_ecbctx *ctx@ = pointer to ECB context block        \
221  *              @const void *src@ = pointer to source data              \
222  *              @void *dest@ = pointer to destination data              \
223  *              @size_t sz@ = size of block to be encrypted             \
224  *                                                                      \
225  * Returns:     ---                                                     \
226  *                                                                      \
227  * Use:         Decrypts a block with a block cipher in ECB mode, with  \
228  *              ciphertext stealing and other clever tricks.            \
229  *              Essentially, data can be encrypted in arbitrary sized   \
230  *              chunks, although decryption must use the same chunks.   \
231  */                                                                     \
232                                                                         \
233 void pre##_ecbdecrypt(pre##_ecbctx *ctx,                                \
234                         const void *src, void *dest,                    \
235                         size_t sz)                                      \
236 {                                                                       \
237   const octet *s = src;                                                 \
238   octet *d = dest;                                                      \
239                                                                         \
240   /* --- Empty blocks are trivial --- */                                \
241                                                                         \
242   if (!sz)                                                              \
243     return;                                                             \
244                                                                         \
245   /* --- Short blocks aren't allowed in ECB --- *                       \
246    *                                                                    \
247    * There's absolutely nothing secure I can do with them.              \
248    */                                                                   \
249                                                                         \
250   assert(((void)"ECB must have at least one whole block to work with",  \
251           sz >= PRE##_BLKSZ));                                          \
252                                                                         \
253   /* --- Do the main chunk of decryption --- *                          \
254    *                                                                    \
255    * This will do the whole lot if it's a whole number of blocks.       \
256    * Each block is just handed to the block cipher in turn.             \
257    */                                                                   \
258                                                                         \
259   while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) {                  \
260     uint32 x[PRE##_BLKSZ / 4];                                          \
261     BLKC_LOAD(PRE, x, s);                                               \
262     pre##_dblk(&ctx->ctx, x, x);                                        \
263     BLKC_STORE(PRE, d, x);                                              \
264     s += PRE##_BLKSZ;                                                   \
265     d += PRE##_BLKSZ;                                                   \
266     sz -= PRE##_BLKSZ;                                                  \
267   }                                                                     \
268                                                                         \
269   /* --- Do the tail-end block and bit-left-over --- *                  \
270    *                                                                    \
271    * This isn't very efficient.  That shouldn't matter much.            \
272    */                                                                   \
273                                                                         \
274   if (sz) {                                                             \
275     uint32 x[PRE##_BLKSZ / 4];                                          \
276     octet b[PRE##_BLKSZ];                                               \
277     unsigned i;                                                         \
278                                                                         \
279     /* --- Let @sz@ be the size of the partial block --- */             \
280                                                                         \
281     sz -= PRE##_BLKSZ;                                                  \
282                                                                         \
283     /* --- First stage --- *                                            \
284      *                                                                  \
285      * Take the complete ciphertext block, and decrypt it.  This block  \
286      * is carried over for the next encryption operation.               \
287      */                                                                 \
288                                                                         \
289     BLKC_LOAD(PRE, x, s);                                               \
290     pre##_dblk(&ctx->ctx, x, x);                                        \
291     BLKC_STORE(PRE, b, x);                                              \
292                                                                         \
293     /* --- Second stage --- *                                           \
294      *                                                                  \
295      * The first few bytes are the partial plaintext block.  Write that \
296      * and replace with the partial ciphertext block.  Then decrypt     \
297      * what's left as the complete plaintext.                           \
298      */                                                                 \
299                                                                         \
300     s += PRE##_BLKSZ;                                                   \
301     d += PRE##_BLKSZ;                                                   \
302     for (i = 0; i < sz; i++) {                                          \
303       register octet y = s[i];                                          \
304       d[i] = b[i];                                                      \
305       b[i] = y;                                                         \
306     }                                                                   \
307     BLKC_LOAD(PRE, x, b);                                               \
308     pre##_dblk(&ctx->ctx, x, x);                                        \
309     BLKC_STORE(PRE, d - PRE##_BLKSZ, x);                                \
310   }                                                                     \
311                                                                         \
312   /* --- Done --- */                                                    \
313                                                                         \
314   return;                                                               \
315 }                                                                       \
316                                                                         \
317 /* --- Generic cipher interface --- */                                  \
318                                                                         \
319 static const gcipher_ops gops;                                          \
320                                                                         \
321 typedef struct gctx {                                                   \
322   gcipher c;                                                            \
323   pre##_ecbctx k;                                                       \
324 } gctx;                                                                 \
325                                                                         \
326 static gcipher *ginit(const void *k, size_t sz)                         \
327 {                                                                       \
328   gctx *g = S_CREATE(gctx);                                             \
329   g->c.ops = &gops;                                                     \
330   pre##_ecbinit(&g->k, k, sz, 0);                                       \
331   return (&g->c);                                                       \
332 }                                                                       \
333                                                                         \
334 static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)     \
335 {                                                                       \
336   gctx *g = (gctx *)c;                                                  \
337   pre##_ecbencrypt(&g->k, s, t, sz);                                    \
338 }                                                                       \
339                                                                         \
340 static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz)     \
341 {                                                                       \
342   gctx *g = (gctx *)c;                                                  \
343   pre##_ecbdecrypt(&g->k, s, t, sz);                                    \
344 }                                                                       \
345                                                                         \
346 static void gdestroy(gcipher *c)                                        \
347 {                                                                       \
348   gctx *g = (gctx *)c;                                                  \
349   BURN(*g);                                                             \
350   S_DESTROY(g);                                                         \
351 }                                                                       \
352                                                                         \
353 static const gcipher_ops gops = {                                       \
354   &pre##_ecb,                                                           \
355   gencrypt, gdecrypt, gdestroy, 0, 0                                    \
356 };                                                                      \
357                                                                         \
358 const gccipher pre##_ecb = {                                            \
359   #pre "-ecb", pre##_keysz, PRE##_BLKSZ,                                \
360   ginit                                                                 \
361 };                                                                      \
362                                                                         \
363 ECB_TEST(PRE, pre)
364
365 /*----- Test rig ----------------------------------------------------------*/
366
367 #ifdef TEST_RIG
368
369 #include <stdio.h>
370
371 #include "daftstory.h"
372
373 /* --- @ECB_TEST@ --- *
374  *
375  * Arguments:   @PRE@, @pre@ = prefixes for block cipher definitions
376  *
377  * Use:         Standard test rig for ECB functions.
378  */
379
380 #define ECB_TEST(PRE, pre)                                              \
381                                                                         \
382 /* --- Initial plaintext for the test --- */                            \
383                                                                         \
384 static const octet text[] = TEXT;                                       \
385                                                                         \
386 /* --- Key and IV to use --- */                                         \
387                                                                         \
388 static const octet key[] = KEY;                                         \
389 static const octet iv[] = IV;                                           \
390                                                                         \
391 /* --- Buffers for encryption and decryption output --- */              \
392                                                                         \
393 static octet ct[sizeof(text)];                                          \
394 static octet pt[sizeof(text)];                                          \
395                                                                         \
396 static void hexdump(const octet *p, size_t sz)                          \
397 {                                                                       \
398   const octet *q = p + sz;                                              \
399   for (sz = 0; p < q; p++, sz++) {                                      \
400     printf("%02x", *p);                                                 \
401     if ((sz + 1) % PRE##_BLKSZ == 0)                                    \
402       putchar(':');                                                     \
403   }                                                                     \
404 }                                                                       \
405                                                                         \
406 int main(void)                                                          \
407 {                                                                       \
408   size_t sz = 0, rest;                                                  \
409   pre##_ecbctx ctx;                                                     \
410   int status = 0;                                                       \
411   int done = 0;                                                         \
412                                                                         \
413   size_t keysz = PRE##_KEYSZ ?                                          \
414     PRE##_KEYSZ : strlen((const char *)key);                            \
415                                                                         \
416   fputs(#pre "-ecb: ", stdout);                                         \
417                                                                         \
418   pre##_ecbinit(&ctx, key, keysz, iv);                                  \
419                                                                         \
420   while (sz <= sizeof(text)) {                                          \
421     rest = sizeof(text) - sz;                                           \
422     if ((sz != 0 && sz < PRE##_BLKSZ) ||                                \
423         (rest != 0 && rest < PRE##_BLKSZ))                              \
424       goto next;                                                        \
425     memcpy(ct, text, sizeof(text));                                     \
426     pre##_ecbencrypt(&ctx, ct, ct, sz);                                 \
427     pre##_ecbencrypt(&ctx, ct + sz, ct + sz, rest);                     \
428     memcpy(pt, ct, sizeof(text));                                       \
429     pre##_ecbdecrypt(&ctx, pt, pt, sz);                                 \
430     pre##_ecbdecrypt(&ctx, pt + sz, pt + sz, rest);                     \
431     if (memcmp(pt, text, sizeof(text)) == 0) {                          \
432       done++;                                                           \
433       if (sizeof(text) < 40 || done % 8 == 0)                           \
434         fputc('.', stdout);                                             \
435       if (done % 480 == 0)                                              \
436         fputs("\n\t", stdout);                                          \
437       fflush(stdout);                                                   \
438     } else {                                                            \
439       printf("\nError (sz = %lu)\n", (unsigned long)sz);                \
440       status = 1;                                                       \
441       printf("\tplaintext      = "); hexdump(text, sz);                 \
442         printf(", "); hexdump(text + sz, rest);                         \
443         fputc('\n', stdout);                                            \
444       printf("\tciphertext     = "); hexdump(ct, sz);                   \
445         printf(", "); hexdump(ct + sz, rest);                           \
446         fputc('\n', stdout);                                            \
447       printf("\trecovered text = "); hexdump(pt, sz);                   \
448         printf(", "); hexdump(pt + sz, rest);                           \
449         fputc('\n', stdout);                                            \
450       fputc('\n', stdout);                                              \
451     }                                                                   \
452   next:                                                                 \
453     if (sz < 63)                                                        \
454       sz++;                                                             \
455     else                                                                \
456       sz += 9;                                                          \
457   }                                                                     \
458                                                                         \
459   fputs(status ? " failed\n" : " ok\n", stdout);                        \
460   return (status);                                                      \
461 }
462
463 #else
464 #  define ECB_TEST(PRE, pre)
465 #endif
466
467 /*----- That's all, folks -------------------------------------------------*/
468
469 #ifdef __cplusplus
470   }
471 #endif
472
473 #endif