Commit | Line | Data |
---|---|---|
d03ab969 | 1 | /* -*-c-*- |
2 | * | |
d03ab969 | 3 | * Common definitions for block ciphers |
4 | * | |
5 | * (c) 1999 Straylight/Edgeware | |
6 | */ | |
7 | ||
45c0fd36 | 8 | /*----- Licensing notice --------------------------------------------------* |
d03ab969 | 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. | |
45c0fd36 | 16 | * |
d03ab969 | 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. | |
45c0fd36 | 21 | * |
d03ab969 | 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 | ||
b3f05084 | 28 | #ifndef CATACOMB_BLKC_H |
29 | #define CATACOMB_BLKC_H | |
d03ab969 | 30 | |
31 | #ifdef __cplusplus | |
32 | extern "C" { | |
33 | #endif | |
34 | ||
35 | /*----- Header files ------------------------------------------------------*/ | |
36 | ||
c5885da8 | 37 | #include <assert.h> |
38 | ||
d03ab969 | 39 | #include <mLib/bits.h> |
40 | ||
41 | /*----- Theory of operation -----------------------------------------------* | |
42 | * | |
43 | * A block cipher has associated with it a triple, called PRE_CLASS, of the | |
44 | * form `(TYPE, ENDIAN, BITS)', where TYPE is either `N' (representing an | |
45 | * implemented bit size) or `X' (representing an unimplemented bit size, | |
46 | * causing loops to be compiled rather than unrolled code), ENDIAN is `B' | |
47 | * (big) or `L' (little), and BITS is the block size of the cipher in bits. | |
48 | */ | |
49 | ||
50 | /*----- Data movement macros ----------------------------------------------*/ | |
51 | ||
52 | /* | |
53 | * `The C preprocessor. You will never find a more wretched hive of bogus | |
54 | * hackery. We must be cautious.' | |
55 | */ | |
56 | ||
57 | /* --- General dispatch macros --- */ | |
58 | ||
59 | #define BLKC_DOGLUE(x, y) x ## y | |
60 | #define BLKC_GLUE(x, y) BLKC_DOGLUE(x, y) | |
61 | #define BLKC_APPLY(f, x) f x | |
62 | #define BLKC_FIRST(x, y, z) x | |
63 | #define BLKC_SECOND(x, y, z) y | |
64 | #define BLKC_THIRD(x, y, z) z | |
b3f05084 | 65 | #define BLKC_TYPE(PRE) BLKC_APPLY(BLKC_FIRST, PRE##_CLASS) |
66 | #define BLKC_ENDIAN(PRE) BLKC_APPLY(BLKC_SECOND, PRE##_CLASS) | |
67 | #define BLKC_BITS(PRE) BLKC_APPLY(BLKC_THIRD, PRE##_CLASS) | |
d03ab969 | 68 | |
69 | #define BLKC_STORE_E(PRE) BLKC_GLUE(STORE32_, BLKC_ENDIAN(PRE)) | |
70 | #define BLKC_LOAD_E(PRE) BLKC_GLUE(LOAD32_, BLKC_ENDIAN(PRE)) | |
71 | ||
72 | /* --- Interface macros --- */ | |
73 | ||
74 | #define BLKC_STORE(PRE, b, w) \ | |
75 | BLKC_GLUE(BLKC_STORE_, BLKC_TYPE(PRE)) \ | |
76 | (PRE, b, w, BLKC_STORE_E(PRE), BLKC_BITS(PRE)) | |
77 | ||
78 | #define BLKC_XSTORE(PRE, b, w, wx) \ | |
79 | BLKC_GLUE(BLKC_XSTORE_, BLKC_TYPE(PRE)) \ | |
80 | (PRE, b, w, wx, BLKC_STORE_E(PRE), BLKC_BITS(PRE)) | |
81 | ||
82 | #define BLKC_LOAD(PRE, w, b) \ | |
83 | BLKC_GLUE(BLKC_LOAD_, BLKC_TYPE(PRE)) \ | |
84 | (PRE, w, b, BLKC_LOAD_E(PRE), BLKC_BITS(PRE)) | |
85 | ||
86 | #define BLKC_XLOAD(PRE, w, b) \ | |
87 | BLKC_GLUE(BLKC_XLOAD_, BLKC_TYPE(PRE)) \ | |
88 | (PRE, w, b, BLKC_LOAD_E(PRE), BLKC_BITS(PRE)) | |
89 | ||
90 | #define BLKC_MOVE(PRE, w, wx) \ | |
91 | BLKC_GLUE(BLKC_MOVE_, BLKC_TYPE(PRE)) \ | |
92 | (PRE, w, wx, BLKC_BITS(PRE)) | |
93 | ||
94 | #define BLKC_XMOVE(PRE, w, wx) \ | |
95 | BLKC_GLUE(BLKC_XMOVE_, BLKC_TYPE(PRE)) \ | |
96 | (PRE, w, wx, BLKC_BITS(PRE)) | |
97 | ||
8ff32af3 MW |
98 | #define BLKC_STEP(PRE, w) BLKC_ADD(PRE, w, 1) |
99 | ||
100 | #define BLKC_ADD(PRE, w, n) \ | |
101 | BLKC_GLUE(BLKC_ADD_X_, BLKC_ENDIAN(PRE)) \ | |
102 | (PRE, w, n) | |
c5885da8 | 103 | |
5c3f75ec | 104 | #define BLKC_ZERO(PRE, w) \ |
105 | BLKC_GLUE(BLKC_ZERO_, BLKC_TYPE(PRE)) \ | |
106 | (PRE, w, BLKC_BITS(PRE)) | |
107 | ||
c5885da8 | 108 | #define BLKC_SET(PRE, w, x) \ |
109 | BLKC_GLUE(BLKC_SET_X_, BLKC_ENDIAN(PRE)) \ | |
110 | (PRE, w, x) | |
111 | ||
112 | #define BLKC_SHOW(PRE, tag, w) do { \ | |
113 | fputs(tag ": ", stdout); \ | |
514871e7 | 114 | BLKC_SKEL_X(PRE, const BLKC_W(w);, printf("%08x ", *_w++);); \ |
c5885da8 | 115 | fputc('\n', stdout); \ |
116 | } while (0) | |
117 | ||
8ff32af3 MW |
118 | /* --- Utilities --- * |
119 | * | |
120 | * These seem too hard to properly generalize, or I'd have put them in | |
121 | * <mLib/bits.h>. | |
122 | */ | |
123 | ||
124 | #ifdef HAVE_UINT64 | |
125 | # define BLKC_ADDC32(z_out, c_out, x, y) do { \ | |
126 | uint64 _t = (uint64)(x) + (y); \ | |
127 | (z_out) = U32(_t); (c_out) = _t >> 32; \ | |
128 | } while (0) | |
129 | #else | |
130 | # define BLKC_ADDC32(z_out, c_out, x, y) do { \ | |
131 | uint32 _x = (x), _c = 0, _t; \ | |
132 | _t = U32(_x + (y)); (z_out) = _t; (c_out) = (_t < _x); \ | |
133 | } while (0) | |
134 | #endif | |
135 | ||
d03ab969 | 136 | /* --- General implementation skeleton --- */ |
137 | ||
138 | #define BLKC_SKEL(PRE, decl, guts) do { \ | |
139 | decl \ | |
140 | guts \ | |
141 | } while (0) | |
142 | ||
0fee61eb MW |
143 | #define BLKC_P(p) octet *_p = (octet *)(p) |
144 | #define BLKC_W(w) uint32 *_w = (w) | |
145 | #define BLKC_WX(wx) uint32 *_wx = (wx) | |
d03ab969 | 146 | |
147 | /* --- Implementation for unusual block sizes --- */ | |
148 | ||
149 | #define BLKC_SKEL_X(PRE, decl, guts) \ | |
c5885da8 | 150 | BLKC_SKEL(PRE, unsigned _i; decl, \ |
0fee61eb | 151 | for (_i = 0; _i < PRE##_BLKSZ/4; _i++) { \ |
d03ab969 | 152 | guts \ |
153 | }) | |
154 | ||
155 | #define BLKC_STORE_X(PRE, b, w, op, n) \ | |
156 | BLKC_SKEL_X(PRE, BLKC_P(b); const BLKC_W(w);, \ | |
157 | op(_p, *_w); _p += 4; _w++; ) | |
158 | ||
159 | #define BLKC_XSTORE_X(PRE, b, w, wx, op, n) \ | |
160 | BLKC_SKEL_X(PRE, BLKC_P(b); const BLKC_W(w); const BLKC_WX(wx);, \ | |
161 | op(_p, *_w ^ *_wx); _p += 4; _w++; _wx++; ) | |
162 | ||
163 | #define BLKC_LOAD_X(PRE, w, b, op, n) \ | |
164 | BLKC_SKEL_X(PRE, const BLKC_P(b); BLKC_W(w);, \ | |
165 | *_w = op(_p); _p += 4; _w++; ) | |
166 | ||
167 | #define BLKC_XLOAD_X(PRE, w, b, op, n) \ | |
168 | BLKC_SKEL_X(PRE, const BLKC_P(b); BLKC_W(w);, \ | |
169 | *_w ^= op(_p); _p += 4; _w++; ) | |
170 | ||
171 | #define BLKC_MOVE_X(PRE, w, wx, n) \ | |
172 | BLKC_SKEL_X(PRE, BLKC_W(w); const BLKC_WX(wx);, \ | |
173 | *_w = *_wx; _w++; _wx++; ) \ | |
174 | ||
175 | #define BLKC_XMOVE_X(PRE, w, wx, n) \ | |
176 | BLKC_SKEL_X(PRE, BLKC_W(w); const BLKC_WX(wx);, \ | |
177 | *_w ^= *_wx; _w++; _wx++; ) \ | |
178 | ||
5c3f75ec | 179 | #define BLKC_ZERO_X(PRE, w, n) \ |
180 | BLKC_SKEL_X(PRE, BLKC_W(w);, *_w++ = 0;) | |
181 | ||
8ff32af3 MW |
182 | #define BLKC_ADD_X_B(PRE, w, n) do { \ |
183 | unsigned _i = PRE##_BLKSZ/4; BLKC_W(w); uint32 _n = (n); \ | |
184 | while (_i-- && _n) BLKC_ADDC32(_w[_i], _n, _w[_i], _n); \ | |
c5885da8 | 185 | } while (0) |
186 | ||
8ff32af3 MW |
187 | #define BLKC_ADD_X_L(PRE, w, n) do { \ |
188 | unsigned _i = 0; BLKC_W(w); uint32 _n = (n); \ | |
189 | while (_i < PRE##_BLKSZ/4 && _n) \ | |
190 | { BLKC_ADDC32(_w[_i], _n, _w[_i], _n); _i++; } \ | |
c5885da8 | 191 | } while (0) |
192 | ||
193 | #define BLKC_SET_X_B(PRE, w, x) do { \ | |
194 | unsigned _i; BLKC_W(w); unsigned long _x = x; \ | |
0fee61eb | 195 | for (_i = 0; _i < PRE##_BLKSZ/4; _i++) { \ |
c5885da8 | 196 | *_w++ = U32(_x); \ |
e91d142c | 197 | _x = ((_x & ~(unsigned long)MASK32) >> 16) >> 16; \ |
c5885da8 | 198 | } \ |
199 | } while (0) | |
200 | ||
201 | #define BLKC_SET_X_L(PRE, w, x) do { \ | |
0fee61eb MW |
202 | unsigned _i; BLKC_W(w); unsigned long _x = x; _w += PRE##_BLKSZ/4; \ |
203 | for (_i = 0; _i < PRE##_BLKSZ/4; _i++) { \ | |
c5885da8 | 204 | *--_w = U32(_x); \ |
e91d142c | 205 | _x = ((_x & ~(unsigned long)MASK32) >> 16) >> 16; \ |
c5885da8 | 206 | } \ |
207 | } while (0) | |
208 | ||
d03ab969 | 209 | /* --- Implementation for known block sizes --- */ |
210 | ||
211 | #define BLKC_SKEL_64(PRE, decl, op, guts) \ | |
212 | BLKC_SKEL(PRE, decl, guts(op, 0); guts(op, 1);) | |
213 | ||
c5885da8 | 214 | #define BLKC_SKEL_96(PRE, decl, op, guts) \ |
215 | BLKC_SKEL(PRE, decl, guts(op, 0); guts(op, 1); guts(op, 2);) | |
216 | ||
d03ab969 | 217 | #define BLKC_SKEL_128(PRE, decl, op, guts) \ |
218 | BLKC_SKEL(PRE, decl, guts(op, 0); guts(op, 1); guts(op, 2); guts(op, 3);) | |
219 | ||
70f31709 | 220 | #define BLKC_SKEL_192(PRE, decl, op, guts) \ |
221 | BLKC_SKEL(PRE, decl, \ | |
222 | guts(op, 0); guts(op, 1); guts(op, 2); guts(op, 3); \ | |
223 | guts(op, 4); guts(op, 5);) | |
224 | ||
225 | #define BLKC_SKEL_256(PRE, decl, op, guts) \ | |
226 | BLKC_SKEL(PRE, decl, \ | |
227 | guts(op, 0); guts(op, 1); guts(op, 2); guts(op, 3); \ | |
228 | guts(op, 4); guts(op, 5); guts(op, 6); guts(op, 7);) | |
229 | ||
d03ab969 | 230 | #define BLKC_STORE_GUTS(op, i) op(_p + 4 * i, _w[i]) |
231 | #define BLKC_XSTORE_GUTS(op, i) op(_p + 4 * i, _w[i] ^ _wx[i]) | |
232 | #define BLKC_LOAD_GUTS(op, i) _w[i] = op(_p + 4 * i) | |
233 | #define BLKC_XLOAD_GUTS(op, i) _w[i] ^= op(_p + 4 * i) | |
234 | #define BLKC_MOVE_GUTS(op, i) _w[i] = _wx[i] | |
235 | #define BLKC_XMOVE_GUTS(op, i) _w[i] ^= _wx[i] | |
5c3f75ec | 236 | #define BLKC_ZERO_GUTS(op, i) _w[i] = 0 |
d03ab969 | 237 | |
238 | #define BLKC_STORE_N(PRE, b, w, op, n) \ | |
239 | BLKC_GLUE(BLKC_SKEL_, n) \ | |
240 | (PRE, BLKC_P(b); const BLKC_W(w);, op, BLKC_STORE_GUTS) | |
241 | ||
242 | #define BLKC_XSTORE_N(PRE, b, w, wx, op, n) \ | |
243 | BLKC_GLUE(BLKC_SKEL_, n) \ | |
244 | (PRE, BLKC_P(b); const BLKC_W(w); const BLKC_WX(wx);, \ | |
245 | op, BLKC_XSTORE_GUTS) | |
246 | ||
247 | #define BLKC_LOAD_N(PRE, w, b, op, n) \ | |
248 | BLKC_GLUE(BLKC_SKEL_, n) \ | |
249 | (PRE, const BLKC_P(b); BLKC_W(w);, op, BLKC_LOAD_GUTS) | |
250 | ||
251 | #define BLKC_XLOAD_N(PRE, w, b, op, n) \ | |
252 | BLKC_GLUE(BLKC_SKEL_, n) \ | |
253 | (PRE, const BLKC_P(b); BLKC_W(w);, op, BLKC_XLOAD_GUTS) | |
254 | ||
255 | #define BLKC_MOVE_N(PRE, w, wx, n) \ | |
256 | BLKC_GLUE(BLKC_SKEL_, n) \ | |
257 | (PRE, BLKC_W(w); const BLKC_WX(wx);, op, BLKC_MOVE_GUTS) | |
258 | ||
5c3f75ec | 259 | #define BLKC_ZERO_N(PRE, w, n) \ |
260 | BLKC_GLUE(BLKC_SKEL_, n) \ | |
261 | (PRE, BLKC_W(w); , op, BLKC_ZERO_GUTS) | |
262 | ||
d03ab969 | 263 | #define BLKC_XMOVE_N(PRE, w, wx, n) \ |
264 | BLKC_GLUE(BLKC_SKEL_, n) \ | |
265 | (PRE, BLKC_W(w); const BLKC_WX(wx);, op, BLKC_XMOVE_GUTS) | |
266 | ||
267 | /*----- Test rig for block ciphers ----------------------------------------*/ | |
268 | ||
269 | /* --- @BLKC_TEST@ --- * | |
270 | * | |
271 | * Arguments: @PRE@, @pre@ = prefixes for cipher-specific definitions | |
272 | * | |
273 | * Use: Standard test rig for block ciphers. | |
274 | */ | |
275 | ||
276 | #ifdef TEST_RIG | |
277 | ||
f94b972d | 278 | #include <string.h> |
45c0fd36 | 279 | |
d03ab969 | 280 | #include <mLib/quis.h> |
281 | #include <mLib/testrig.h> | |
282 | ||
aaae9cab MW |
283 | #define BLKC_VERIFY(PRE, pre) BLKC_VERIFYX(PRE, pre, #pre) |
284 | ||
285 | #define BLKC_VERIFYX(PRE, pre, name) \ | |
d03ab969 | 286 | \ |
dcdc42e7 | 287 | static int pre##_verify(dstr *v) \ |
d03ab969 | 288 | { \ |
b3f05084 | 289 | pre##_ctx k; \ |
0fee61eb MW |
290 | uint32 p[PRE##_BLKSZ/4]; \ |
291 | uint32 c[PRE##_BLKSZ/4]; \ | |
292 | uint32 d[PRE##_BLKSZ/4]; \ | |
d03ab969 | 293 | dstr b = DSTR_INIT; \ |
294 | int ok = 1; \ | |
295 | \ | |
296 | /* --- Initialize the key buffer --- */ \ | |
297 | \ | |
b3f05084 | 298 | dstr_ensure(&b, PRE##_BLKSZ); \ |
299 | b.len = PRE##_BLKSZ; \ | |
300 | pre##_init(&k, v[0].buf, v[0].len); \ | |
d03ab969 | 301 | BLKC_LOAD(PRE, p, v[1].buf); \ |
302 | BLKC_LOAD(PRE, c, v[2].buf); \ | |
303 | \ | |
304 | /* --- Test encryption --- */ \ | |
305 | \ | |
306 | BLKC_MOVE(PRE, d, p); \ | |
b3f05084 | 307 | pre##_eblk(&k, d, d); \ |
d03ab969 | 308 | BLKC_STORE(PRE, b.buf, d); \ |
b3f05084 | 309 | if (memcmp(b.buf, v[2].buf, PRE##_BLKSZ)) { \ |
d03ab969 | 310 | ok = 0; \ |
311 | printf("\nfail encryption:" \ | |
45c0fd36 | 312 | "\n\tkey = "); \ |
d03ab969 | 313 | type_hex.dump(&v[0], stdout); \ |
314 | printf("\n\tplaintext = "); type_hex.dump(&v[1], stdout); \ | |
315 | printf("\n\texpected = "); type_hex.dump(&v[2], stdout); \ | |
316 | printf("\n\tcalculated = "); type_hex.dump(&b, stdout); \ | |
317 | putchar('\n'); \ | |
318 | } \ | |
319 | \ | |
320 | /* --- Test decryption --- */ \ | |
321 | \ | |
322 | BLKC_MOVE(PRE, d, c); \ | |
b3f05084 | 323 | pre##_dblk(&k, d, d); \ |
d03ab969 | 324 | BLKC_STORE(PRE, b.buf, d); \ |
b3f05084 | 325 | if (memcmp(b.buf, v[1].buf, PRE##_BLKSZ)) { \ |
d03ab969 | 326 | ok = 0; \ |
327 | printf("\nfail decryption:" \ | |
45c0fd36 | 328 | "\n\tkey = "); \ |
d03ab969 | 329 | type_hex.dump(&v[0], stdout); \ |
330 | printf("\n\tciphertext = "); type_hex.dump(&v[2], stdout); \ | |
331 | printf("\n\texpected = "); type_hex.dump(&v[1], stdout); \ | |
332 | printf("\n\tcalculated = "); type_hex.dump(&b, stdout); \ | |
333 | putchar('\n'); \ | |
334 | } \ | |
335 | \ | |
336 | /* --- Return --- */ \ | |
337 | \ | |
338 | return (ok); \ | |
dcdc42e7 | 339 | } |
340 | ||
4328f746 MW |
341 | #define BLKC_TESTDEFS(PRE, pre) BLKC_TESTDEFSX(PRE, pre, #pre) |
342 | ||
343 | #define BLKC_TESTDEFSX(PRE, pre, name) \ | |
344 | { name, pre##_verify, { &type_hex, &type_hex, &type_hex, 0 } }, | |
345 | ||
aaae9cab | 346 | #define BLKC_TESTX(PRE, pre, name, fname) \ |
dcdc42e7 | 347 | \ |
aaae9cab | 348 | BLKC_VERIFYX(PRE, pre, name) \ |
d03ab969 | 349 | \ |
4e66da02 | 350 | static const test_chunk defs[] = { \ |
4328f746 | 351 | BLKC_TESTDEFSX(PRE, pre, name) \ |
d03ab969 | 352 | { 0, 0, { 0 } } \ |
353 | }; \ | |
354 | \ | |
355 | int main(int argc, char *argv[]) \ | |
356 | { \ | |
aaae9cab | 357 | test_run(argc, argv, defs, SRCDIR"/t/" fname); \ |
d03ab969 | 358 | return (0); \ |
359 | } | |
360 | ||
361 | #else | |
aaae9cab | 362 | # define BLKC_TESTX(PRE, pre, name, fname) |
d03ab969 | 363 | #endif |
364 | ||
aaae9cab MW |
365 | #define BLKC_TEST(PRE, pre) BLKC_TESTX(PRE, pre, #pre, #pre) |
366 | ||
d03ab969 | 367 | /*----- That's all, folks -------------------------------------------------*/ |
368 | ||
369 | #ifdef __cplusplus | |
370 | } | |
371 | #endif | |
372 | ||
373 | #endif |