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