math/mpreduce.h: Missing include files.
[u/mdw/catacomb] / symm / ofb-def.h
CommitLineData
79ba130c 1/* -*-c-*-
2 *
79ba130c 3 * Definitions for output feedback mode
4 *
5 * (c) 1999 Straylight/Edgeware
6 */
7
45c0fd36 8/*----- Licensing notice --------------------------------------------------*
79ba130c 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 *
79ba130c 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 *
79ba130c 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
79ba130c 28#ifndef CATACOMB_OFB_DEF_H
29#define CATACOMB_OFB_DEF_H
30
31#ifdef __cplusplus
32 extern "C" {
33#endif
34
35/*----- Header files ------------------------------------------------------*/
36
37#include <stdarg.h>
38#include <string.h>
39
40#include <mLib/bits.h>
41#include <mLib/sub.h>
42
2af20fa2 43#ifndef CATACOMB_ARENA_H
44# include "arena.h"
45#endif
46
79ba130c 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/* --- @OFB_DEF@ --- *
62 *
63 * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
64 *
65 * Use: Creates definitions for output feedback mode.
66 */
67
68#define OFB_DEF(PRE, pre) \
69 \
70/* --- @pre_ofbgetiv@ --- * \
71 * \
72 * Arguments: @const pre_ofbctx *ctx@ = pointer to OFB context block \
4efe32ba 73 * @void *iv@ = pointer to output data block \
79ba130c 74 * \
75 * Returns: --- \
76 * \
77 * Use: Reads the currently set IV. Reading and setting an IV \
78 * is not transparent to the cipher. It will add a `step' \
79 * which must be matched by a similar operation during \
80 * decryption. \
81 */ \
82 \
83void pre##_ofbgetiv(const pre##_ofbctx *ctx, void *iv) \
84{ \
85 octet *p = iv; \
2af20fa2 86 unsigned off = ctx->off; \
87 unsigned rest = PRE##_BLKSZ - off; \
79ba130c 88 memcpy(p, ctx->iv + off, rest); \
89 memcpy(p + rest, ctx->iv, off); \
90} \
91 \
92/* --- @pre_ofbsetiv@ --- * \
93 * \
94 * Arguments: @pre_ofbctx *ctx@ = pointer to OFB context block \
95 * @cnost void *iv@ = pointer to IV to set \
96 * \
97 * Returns: --- \
98 * \
99 * Use: Sets the IV to use for subsequent encryption. \
100 */ \
101 \
102void pre##_ofbsetiv(pre##_ofbctx *ctx, const void *iv) \
103{ \
2af20fa2 104 memcpy(ctx->iv, iv, PRE##_BLKSZ); \
105 ctx->off = PRE##_BLKSZ; \
79ba130c 106} \
107 \
108/* --- @pre_ofbbdry@ --- * \
109 * \
110 * Arguments: @pre_ofbctx *ctx@ = pointer to OFB context block \
111 * \
112 * Returns: --- \
113 * \
114 * Use: Inserts a boundary during encryption. Successful \
115 * decryption must place a similar boundary. \
116 */ \
117 \
118void pre##_ofbbdry(pre##_ofbctx *ctx) \
119{ \
2af20fa2 120 uint32 niv[PRE##_BLKSZ / 4]; \
121 BLKC_LOAD(PRE, niv, ctx->iv); \
122 pre##_eblk(&ctx->ctx, niv, niv); \
123 BLKC_STORE(PRE, ctx->iv, niv); \
124 ctx->off = PRE##_BLKSZ; \
125 BURN(niv); \
79ba130c 126} \
127 \
128/* --- @pre_ofbsetkey@ --- * \
129 * \
130 * Arguments: @pre_ofbctx *ctx@ = pointer to OFB context block \
131 * @const pre_ctx *k@ = pointer to cipher context \
132 * \
133 * Returns: --- \
134 * \
135 * Use: Sets the OFB context to use a different cipher key. \
136 */ \
137 \
138void pre##_ofbsetkey(pre##_ofbctx *ctx, const pre##_ctx *k) \
139{ \
140 ctx->ctx = *k; \
141} \
142 \
143/* --- @pre_ofbinit@ --- * \
144 * \
145 * Arguments: @pre_ofbctx *ctx@ = pointer to cipher context \
146 * @const void *key@ = pointer to the key buffer \
147 * @size_t sz@ = size of the key \
148 * @const void *iv@ = pointer to initialization vector \
149 * \
150 * Returns: --- \
151 * \
152 * Use: Initializes a OFB context ready for use. You should \
153 * ensure that the IV chosen is unique: reusing an IV will \
154 * compromise the security of the entire plaintext. This \
155 * is equivalent to calls to @pre_init@, @pre_ofbsetkey@ \
156 * and @pre_ofbsetiv@. \
157 */ \
158 \
159void pre##_ofbinit(pre##_ofbctx *ctx, \
160 const void *key, size_t sz, \
161 const void *iv) \
162{ \
4e66da02 163 static const octet zero[PRE##_BLKSZ] = { 0 }; \
79ba130c 164 pre##_init(&ctx->ctx, key, sz); \
165 pre##_ofbsetiv(ctx, iv ? iv : zero); \
166} \
167 \
168/* --- @pre_ofbencrypt@ --- * \
169 * \
170 * Arguments: @pre_ofbctx *ctx@ = pointer to OFB context block \
171 * @const void *src@ = pointer to source data \
172 * @void *dest@ = pointer to destination data \
173 * @size_t sz@ = size of block to be encrypted \
174 * \
175 * Returns: --- \
176 * \
177 * Use: Encrypts or decrypts a block with a block cipher in OFB \
178 * mode: encryption and decryption are the same in OFB. \
179 * The destination may be null to just churn the feedback \
180 * round for a bit. The source may be null to use the \
181 * cipher as a random data generator. \
182 */ \
183 \
184void pre##_ofbencrypt(pre##_ofbctx *ctx, \
185 const void *src, void *dest, \
186 size_t sz) \
187{ \
188 const octet *s = src; \
189 octet *d = dest; \
2af20fa2 190 unsigned off = ctx->off; \
79ba130c 191 \
192 /* --- Empty blocks are trivial --- */ \
193 \
194 if (!sz) \
195 return; \
196 \
197 /* --- If I can deal with the block from my buffer, do that --- */ \
198 \
199 if (sz < PRE##_BLKSZ - off) \
200 goto small; \
201 \
202 /* --- Finish off what's left in my buffer --- */ \
203 \
204 if (!d) \
2af20fa2 205 sz -= PRE##_BLKSZ - off; \
79ba130c 206 else { \
207 while (off < PRE##_BLKSZ) { \
208 register octet x = s ? *s++ : 0; \
209 *d++ = ctx->iv[off++] ^ x; \
210 sz--; \
211 } \
212 } \
213 \
214 /* --- Main encryption loop --- */ \
215 \
216 { \
217 uint32 iv[PRE##_BLKSZ / 4]; \
218 BLKC_LOAD(PRE, iv, ctx->iv); \
219 \
220 for (;;) { \
221 pre##_eblk(&ctx->ctx, iv, iv); \
222 if (sz < PRE##_BLKSZ) \
223 break; \
224 if (d) { \
225 if (!s) \
226 BLKC_STORE(PRE, d, iv); \
227 else { \
228 uint32 x[PRE##_BLKSZ / 4]; \
229 BLKC_LOAD(PRE, x, s); \
230 BLKC_XSTORE(PRE, d, iv, x); \
231 s += PRE##_BLKSZ; \
232 } \
233 d += PRE##_BLKSZ; \
234 } \
235 sz -= PRE##_BLKSZ; \
236 } \
237 \
238 BLKC_STORE(PRE, ctx->iv, iv); \
239 off = 0; \
240 } \
241 \
242 /* --- Tidying up the tail end --- */ \
243 \
244 if (sz) { \
245 small: \
246 if (!d) \
247 off += sz; \
248 else do { \
249 register octet x = s ? *s++ : 0; \
250 *d++ = ctx->iv[off++] ^ x; \
251 sz--; \
252 } while (sz); \
253 } \
254 \
255 /* --- Done --- */ \
256 \
257 ctx->off = off; \
258 return; \
259} \
260 \
261/* --- Generic cipher interface --- */ \
262 \
263static const gcipher_ops gops; \
264 \
265typedef struct gctx { \
266 gcipher c; \
267 pre##_ofbctx k; \
268} gctx; \
269 \
270static gcipher *ginit(const void *k, size_t sz) \
271{ \
2af20fa2 272 gctx *g = S_CREATE(gctx); \
79ba130c 273 g->c.ops = &gops; \
274 pre##_ofbinit(&g->k, k, sz, 0); \
275 return (&g->c); \
276} \
277 \
278static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) \
279{ \
280 gctx *g = (gctx *)c; \
281 pre##_ofbencrypt(&g->k, s, t, sz); \
282} \
283 \
284static void gdestroy(gcipher *c) \
285{ \
286 gctx *g = (gctx *)c; \
2af20fa2 287 BURN(*g); \
288 S_DESTROY(g); \
79ba130c 289} \
290 \
291static void gsetiv(gcipher *c, const void *iv) \
292{ \
293 gctx *g = (gctx *)c; \
294 pre##_ofbsetiv(&g->k, iv); \
295} \
296 \
297static void gbdry(gcipher *c) \
298{ \
299 gctx *g = (gctx *)c; \
300 pre##_ofbbdry(&g->k); \
301} \
302 \
303static const gcipher_ops gops = { \
2af20fa2 304 &pre##_ofb, \
79ba130c 305 gencrypt, gencrypt, gdestroy, gsetiv, gbdry \
306}; \
307 \
308const gccipher pre##_ofb = { \
2af20fa2 309 #pre "-ofb", pre##_keysz, PRE##_BLKSZ, \
79ba130c 310 ginit \
311}; \
312 \
313/* --- Generic random number generator interface --- */ \
314 \
315typedef struct grctx { \
316 grand r; \
317 pre##_ofbctx k; \
318} grctx; \
319 \
320static void grdestroy(grand *r) \
321{ \
322 grctx *g = (grctx *)r; \
2af20fa2 323 BURN(*g); \
324 S_DESTROY(g); \
79ba130c 325} \
326 \
327static int grmisc(grand *r, unsigned op, ...) \
328{ \
329 grctx *g = (grctx *)r; \
330 va_list ap; \
331 int rc = 0; \
360c232e 332 uint32 i; \
79ba130c 333 octet buf[PRE##_BLKSZ]; \
334 va_start(ap, op); \
335 \
336 switch (op) { \
337 case GRAND_CHECK: \
338 switch (va_arg(ap, unsigned)) { \
339 case GRAND_CHECK: \
340 case GRAND_SEEDINT: \
341 case GRAND_SEEDUINT32: \
342 case GRAND_SEEDBLOCK: \
4ab1268f 343 case GRAND_SEEDRAND: \
79ba130c 344 rc = 1; \
345 break; \
346 default: \
347 rc = 0; \
348 break; \
349 } \
350 break; \
351 case GRAND_SEEDINT: \
352 memset(buf, 0, sizeof(buf)); \
360c232e 353 i = va_arg(ap, unsigned); \
354 STORE32(buf, i); \
79ba130c 355 pre##_ofbsetiv(&g->k, buf); \
356 break; \
357 case GRAND_SEEDUINT32: \
358 memset(buf, 0, sizeof(buf)); \
360c232e 359 i = va_arg(ap, uint32); \
360 STORE32(buf, i); \
79ba130c 361 pre##_ofbsetiv(&g->k, buf); \
362 break; \
363 case GRAND_SEEDBLOCK: { \
364 const void *p = va_arg(ap, const void *); \
365 size_t sz = va_arg(ap, size_t); \
366 if (sz < sizeof(buf)) { \
367 memset(buf, 0, sizeof(buf)); \
368 memcpy(buf, p, sz); \
369 p = buf; \
370 } \
371 pre##_ofbsetiv(&g->k, p); \
372 } break; \
4ab1268f 373 case GRAND_SEEDRAND: { \
374 grand *rr = va_arg(ap, grand *); \
375 rr->ops->fill(rr, buf, sizeof(buf)); \
376 pre##_ofbsetiv(&g->k, buf); \
377 } break; \
378 default: \
379 GRAND_BADOP; \
380 break; \
79ba130c 381 } \
382 \
383 va_end(ap); \
384 return (rc); \
385} \
386 \
387static octet grbyte(grand *r) \
388{ \
389 grctx *g = (grctx *)r; \
390 octet o; \
391 pre##_ofbencrypt(&g->k, 0, &o, 1); \
392 return (o); \
393} \
394 \
395static uint32 grword(grand *r) \
396{ \
397 grctx *g = (grctx *)r; \
398 octet b[4]; \
399 pre##_ofbencrypt(&g->k, 0, b, sizeof(b)); \
400 return (LOAD32(b)); \
401} \
402 \
403static void grfill(grand *r, void *p, size_t sz) \
404{ \
405 grctx *g = (grctx *)r; \
406 pre##_ofbencrypt(&g->k, 0, p, sz); \
407} \
408 \
409static const grand_ops grops = { \
410 #pre "-ofb", \
2af20fa2 411 GRAND_CRYPTO, 0, \
79ba130c 412 grmisc, grdestroy, \
413 grword, grbyte, grword, grand_range, grfill \
414}; \
415 \
416/* --- @pre_ofbrand@ --- * \
417 * \
418 * Arguments: @const void *k@ = pointer to key material \
419 * @size_t sz@ = size of key material \
420 * \
421 * Returns: Pointer to generic random number generator interface. \
422 * \
423 * Use: Creates a random number interface wrapper around an \
424 * OFB-mode block cipher. \
425 */ \
426 \
427grand *pre##_ofbrand(const void *k, size_t sz) \
428{ \
2af20fa2 429 grctx *g = S_CREATE(grctx); \
79ba130c 430 g->r.ops = &grops; \
431 pre##_ofbinit(&g->k, k, sz, 0); \
432 return (&g->r); \
433} \
434 \
435OFB_TEST(PRE, pre)
436
437/*----- Test rig ----------------------------------------------------------*/
438
439#ifdef TEST_RIG
440
441#include <stdio.h>
442
443#include "daftstory.h"
444
445/* --- @OFB_TEST@ --- *
446 *
447 * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions
448 *
449 * Use: Standard test rig for OFB functions.
450 */
451
452#define OFB_TEST(PRE, pre) \
453 \
454/* --- Initial plaintext for the test --- */ \
455 \
456static const octet text[] = TEXT; \
457 \
458/* --- Key and IV to use --- */ \
459 \
460static const octet key[] = KEY; \
461static const octet iv[] = IV; \
462 \
463/* --- Buffers for encryption and decryption output --- */ \
464 \
465static octet ct[sizeof(text)]; \
466static octet pt[sizeof(text)]; \
467 \
468static void hexdump(const octet *p, size_t sz) \
469{ \
470 const octet *q = p + sz; \
471 for (sz = 0; p < q; p++, sz++) { \
472 printf("%02x", *p); \
473 if ((sz + 1) % PRE##_BLKSZ == 0) \
474 putchar(':'); \
475 } \
476} \
477 \
478int main(void) \
479{ \
480 size_t sz = 0, rest; \
481 pre##_ofbctx ctx; \
482 int status = 0; \
483 int done = 0; \
484 pre##_ctx k; \
485 \
486 size_t keysz = PRE##_KEYSZ ? \
487 PRE##_KEYSZ : strlen((const char *)key); \
488 \
489 fputs(#pre "-ofb: ", stdout); \
490 \
491 pre##_init(&k, key, keysz); \
492 pre##_ofbsetkey(&ctx, &k); \
493 \
494 while (sz <= sizeof(text)) { \
495 rest = sizeof(text) - sz; \
496 memcpy(ct, text, sizeof(text)); \
497 pre##_ofbsetiv(&ctx, iv); \
498 pre##_ofbencrypt(&ctx, ct, ct, sz); \
499 pre##_ofbencrypt(&ctx, ct + sz, ct + sz, rest); \
500 memcpy(pt, ct, sizeof(text)); \
501 pre##_ofbsetiv(&ctx, iv); \
502 pre##_ofbencrypt(&ctx, pt, pt, rest); \
503 pre##_ofbencrypt(&ctx, pt + rest, pt + rest, sz); \
504 if (memcmp(pt, text, sizeof(text)) == 0) { \
505 done++; \
506 if (sizeof(text) < 40 || done % 8 == 0) \
45c0fd36 507 fputc('.', stdout); \
79ba130c 508 if (done % 480 == 0) \
45c0fd36 509 fputs("\n\t", stdout); \
79ba130c 510 fflush(stdout); \
511 } else { \
512 printf("\nError (sz = %lu)\n", (unsigned long)sz); \
513 status = 1; \
514 printf("\tplaintext = "); hexdump(text, sz); \
45c0fd36
MW
515 printf(", "); hexdump(text + sz, rest); \
516 fputc('\n', stdout); \
79ba130c 517 printf("\tciphertext = "); hexdump(ct, sz); \
45c0fd36
MW
518 printf(", "); hexdump(ct + sz, rest); \
519 fputc('\n', stdout); \
79ba130c 520 printf("\trecovered text = "); hexdump(pt, sz); \
45c0fd36
MW
521 printf(", "); hexdump(pt + sz, rest); \
522 fputc('\n', stdout); \
79ba130c 523 fputc('\n', stdout); \
524 } \
525 if (sz < 63) \
526 sz++; \
527 else \
528 sz += 9; \
529 } \
530 \
531 fputs(status ? " failed\n" : " ok\n", stdout); \
532 return (status); \
533}
534
535#else
536# define OFB_TEST(PRE, pre)
537#endif
538
539/*----- That's all, folks -------------------------------------------------*/
540
541#ifdef __cplusplus
542 }
543#endif
544
545#endif