Table for driving key data extraction.
[u/mdw/catacomb] / ecb-def.h
CommitLineData
79ba130c 1/* -*-c-*-
2 *
3 * $Id: ecb-def.h,v 1.1 1999/12/10 23:16:39 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.1 1999/12/10 23:16:39 mdw
34 * Split mode macros into interface and implementation.
35 *
36 */
37
38#ifndef CATACOMB_ECB_DEF_H
39#define CATACOMB_ECB_DEF_H
40
41#ifdef __cplusplus
42 extern "C" {
43#endif
44
45/*----- Header files ------------------------------------------------------*/
46
47#include <assert.h>
48#include <string.h>
49
50#include <mLib/bits.h>
51#include <mLib/sub.h>
52
53#ifndef CATACOMB_BLKC_H
54# include "blkc.h"
55#endif
56
57#ifndef CATACOMB_GCIPHER_H
58# include "gcipher.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 \
82void 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 \
100void 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 \
122void 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 \
223void 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 \
309static const gcipher_ops gops; \
310 \
311typedef struct gctx { \
312 gcipher c; \
313 pre##_ecbctx k; \
314} gctx; \
315 \
316static gcipher *ginit(const void *k, size_t sz) \
317{ \
318 gctx *g = CREATE(gctx); \
319 g->c.ops = &gops; \
320 pre##_ecbinit(&g->k, k, sz, 0); \
321 return (&g->c); \
322} \
323 \
324static 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 \
330static 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 \
336static void gdestroy(gcipher *c) \
337{ \
338 gctx *g = (gctx *)c; \
339 DESTROY(g); \
340} \
341 \
342static const gcipher_ops gops = { \
343 &pre##_ecb.b, \
344 gencrypt, gdecrypt, gdestroy, 0, 0 \
345}; \
346 \
347const gccipher pre##_ecb = { \
348 { #pre "-ecb", PRE##_KEYSZ, PRE##_BLKSZ }, \
349 ginit \
350}; \
351 \
352ECB_TEST(PRE, pre)
353
354/*----- Test rig ----------------------------------------------------------*/
355
356#ifdef TEST_RIG
357
358#include <stdio.h>
359
360#include "daftstory.h"
361
362/* --- @ECB_TEST@ --- *
363 *
364 * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions
365 *
366 * Use: Standard test rig for ECB functions.
367 */
368
369#define ECB_TEST(PRE, pre) \
370 \
371/* --- Initial plaintext for the test --- */ \
372 \
373static const octet text[] = TEXT; \
374 \
375/* --- Key and IV to use --- */ \
376 \
377static const octet key[] = KEY; \
378static const octet iv[] = IV; \
379 \
380/* --- Buffers for encryption and decryption output --- */ \
381 \
382static octet ct[sizeof(text)]; \
383static octet pt[sizeof(text)]; \
384 \
385static void hexdump(const octet *p, size_t sz) \
386{ \
387 const octet *q = p + sz; \
388 for (sz = 0; p < q; p++, sz++) { \
389 printf("%02x", *p); \
390 if ((sz + 1) % PRE##_BLKSZ == 0) \
391 putchar(':'); \
392 } \
393} \
394 \
395int main(void) \
396{ \
397 size_t sz = 0, rest; \
398 pre##_ecbctx ctx; \
399 int status = 0; \
400 int done = 0; \
401 \
402 size_t keysz = PRE##_KEYSZ ? \
403 PRE##_KEYSZ : strlen((const char *)key); \
404 \
405 fputs(#pre "-ecb: ", stdout); \
406 \
407 pre##_ecbinit(&ctx, key, keysz, iv); \
408 \
409 while (sz <= sizeof(text)) { \
410 rest = sizeof(text) - sz; \
411 if ((sz != 0 && sz < PRE##_BLKSZ) || \
412 (rest != 0 && rest < PRE##_BLKSZ)) \
413 goto next; \
414 memcpy(ct, text, sizeof(text)); \
415 pre##_ecbencrypt(&ctx, ct, ct, sz); \
416 pre##_ecbencrypt(&ctx, ct + sz, ct + sz, rest); \
417 memcpy(pt, ct, sizeof(text)); \
418 pre##_ecbdecrypt(&ctx, pt, pt, sz); \
419 pre##_ecbdecrypt(&ctx, pt + sz, pt + sz, rest); \
420 if (memcmp(pt, text, sizeof(text)) == 0) { \
421 done++; \
422 if (sizeof(text) < 40 || done % 8 == 0) \
423 fputc('.', stdout); \
424 if (done % 480 == 0) \
425 fputs("\n\t", stdout); \
426 fflush(stdout); \
427 } else { \
428 printf("\nError (sz = %lu)\n", (unsigned long)sz); \
429 status = 1; \
430 printf("\tplaintext = "); hexdump(text, sz); \
431 printf(", "); hexdump(text + sz, rest); \
432 fputc('\n', stdout); \
433 printf("\tciphertext = "); hexdump(ct, sz); \
434 printf(", "); hexdump(ct + sz, rest); \
435 fputc('\n', stdout); \
436 printf("\trecovered text = "); hexdump(pt, sz); \
437 printf(", "); hexdump(pt + sz, rest); \
438 fputc('\n', stdout); \
439 fputc('\n', stdout); \
440 } \
441 next: \
442 if (sz < 63) \
443 sz++; \
444 else \
445 sz += 9; \
446 } \
447 \
448 fputs(status ? " failed\n" : " ok\n", stdout); \
449 return (status); \
450}
451
452#else
453# define ECB_TEST(PRE, pre)
454#endif
455
456/*----- That's all, folks -------------------------------------------------*/
457
458#ifdef __cplusplus
459 }
460#endif
461
462#endif