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