chiark / gitweb /
symm/chacha.c: Set the correct nonce size for `xchachaNN'.
[catacomb] / symm / ecb-def.h
1 /* -*-c-*-
2  *
3  * Definitions electronic code book mode
4  *
5  * (c) 1999 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
9  *
10  * This file is part of Catacomb.
11  *
12  * Catacomb is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU Library General Public License as
14  * published by the Free Software Foundation; either version 2 of the
15  * License, or (at your option) any later version.
16  *
17  * Catacomb is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public
23  * License along with Catacomb; if not, write to the Free
24  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25  * MA 02111-1307, USA.
26  */
27
28 #ifndef CATACOMB_ECB_DEF_H
29 #define CATACOMB_ECB_DEF_H
30
31 #ifdef __cplusplus
32   extern "C" {
33 #endif
34
35 /*----- Header files ------------------------------------------------------*/
36
37 #include <assert.h>
38 #include <string.h>
39
40 #include <mLib/bits.h>
41 #include <mLib/sub.h>
42
43 #ifndef CATACOMB_ARENA_H
44 #  include "arena.h"
45 #endif
46
47 #ifndef CATACOMB_BLKC_H
48 #  include "blkc.h"
49 #endif
50
51 #ifndef CATACOMB_GCIPHER_H
52 #  include "gcipher.h"
53 #endif
54
55 #ifndef CATACOMB_PARANOIA_H
56 #  include "paranoia.h"
57 #endif
58
59 /*----- Macros ------------------------------------------------------------*/
60
61 /* --- @ECB_DEF@ --- *
62  *
63  * Arguments:   @PRE@, @pre@ = prefixes for the underlying block cipher
64  *
65  * Use:         Creates an implementation for ECB stealing mode.
66  */
67
68 #define ECB_DEF(PRE, pre) ECB_DEFX(PRE, pre, #pre, #pre)
69
70 #define ECB_DEFX(PRE, pre, name, fname)                                 \
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   name "-ecb", pre##_keysz, PRE##_BLKSZ,                                \
360   ginit                                                                 \
361 };                                                                      \
362                                                                         \
363 ECB_TESTX(PRE, pre, name, fname)
364
365 /*----- Test rig ----------------------------------------------------------*/
366
367 #define ECB_TEST(PRE, pre) ECB_TESTX(PRE, pre, #pre, #pre)
368
369 #ifdef TEST_RIG
370
371 #include <stdio.h>
372
373 #include "daftstory.h"
374
375 /* --- @ECB_TEST@ --- *
376  *
377  * Arguments:   @PRE@, @pre@ = prefixes for block cipher definitions
378  *
379  * Use:         Standard test rig for ECB functions.
380  */
381
382 #define ECB_TESTX(PRE, pre, name, fname)                                \
383                                                                         \
384 /* --- Initial plaintext for the test --- */                            \
385                                                                         \
386 static const octet text[] = TEXT;                                       \
387                                                                         \
388 /* --- Key and IV to use --- */                                         \
389                                                                         \
390 static const octet key[] = KEY;                                         \
391 static const octet iv[] = IV;                                           \
392                                                                         \
393 /* --- Buffers for encryption and decryption output --- */              \
394                                                                         \
395 static octet ct[sizeof(text)];                                          \
396 static octet pt[sizeof(text)];                                          \
397                                                                         \
398 static void hexdump(const octet *p, size_t sz, size_t off)              \
399 {                                                                       \
400   const octet *q = p + sz;                                              \
401   for (sz = 0; p < q; p++, sz++) {                                      \
402     printf("%02x", *p);                                                 \
403     if ((off + sz + 1) % PRE##_BLKSZ == 0)                              \
404       putchar(':');                                                     \
405   }                                                                     \
406 }                                                                       \
407                                                                         \
408 int main(void)                                                          \
409 {                                                                       \
410   size_t sz = 0, rest;                                                  \
411   pre##_ecbctx ctx;                                                     \
412   int status = 0;                                                       \
413   int done = 0;                                                         \
414                                                                         \
415   size_t keysz = PRE##_KEYSZ ?                                          \
416     PRE##_KEYSZ : strlen((const char *)key);                            \
417                                                                         \
418   fputs(name "-ecb: ", stdout);                                         \
419                                                                         \
420   pre##_ecbinit(&ctx, key, keysz, iv);                                  \
421                                                                         \
422   while (sz <= sizeof(text)) {                                          \
423     rest = sizeof(text) - sz;                                           \
424     if ((sz != 0 && sz < PRE##_BLKSZ) ||                                \
425         (rest != 0 && rest < PRE##_BLKSZ))                              \
426       goto next;                                                        \
427     memcpy(ct, text, sizeof(text));                                     \
428     pre##_ecbencrypt(&ctx, ct, ct, sz);                                 \
429     pre##_ecbencrypt(&ctx, ct + sz, ct + sz, rest);                     \
430     memcpy(pt, ct, sizeof(text));                                       \
431     pre##_ecbdecrypt(&ctx, pt, pt, sz);                                 \
432     pre##_ecbdecrypt(&ctx, pt + sz, pt + sz, rest);                     \
433     if (memcmp(pt, text, sizeof(text)) == 0) {                          \
434       done++;                                                           \
435       if (sizeof(text) < 40 || done % 8 == 0)                           \
436         fputc('.', stdout);                                             \
437       if (done % 480 == 0)                                              \
438         fputs("\n\t", stdout);                                          \
439       fflush(stdout);                                                   \
440     } else {                                                            \
441       printf("\nError (sz = %lu)\n", (unsigned long)sz);                \
442       status = 1;                                                       \
443       printf("\tplaintext      = "); hexdump(text, sz, 0);              \
444         printf(", "); hexdump(text + sz, rest, sz);                     \
445         fputc('\n', stdout);                                            \
446       printf("\tciphertext     = "); hexdump(ct, sz, 0);                \
447         printf(", "); hexdump(ct + sz, rest, sz);                       \
448         fputc('\n', stdout);                                            \
449       printf("\trecovered text = "); hexdump(pt, sz, 0);                \
450         printf(", "); hexdump(pt + sz, rest, sz);                       \
451         fputc('\n', stdout);                                            \
452       fputc('\n', stdout);                                              \
453     }                                                                   \
454   next:                                                                 \
455     if (sz < 63)                                                        \
456       sz++;                                                             \
457     else                                                                \
458       sz += 9;                                                          \
459   }                                                                     \
460                                                                         \
461   fputs(status ? " failed\n" : " ok\n", stdout);                        \
462   return (status);                                                      \
463 }
464
465 #else
466 #  define ECB_TESTX(PRE, pre, name, fname)
467 #endif
468
469 /*----- That's all, folks -------------------------------------------------*/
470
471 #ifdef __cplusplus
472   }
473 #endif
474
475 #endif