progs/perftest.c: Use from Glibc syscall numbers.
[catacomb] / symm / ocb1-def.h
1 /* -*-c-*-
2 *
3 * The OCB1 authenticated encryption mode
4 *
5 * (c) 2018 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 it
13 * under the terms of the GNU Library General Public License as published
14 * by the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * Catacomb is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * 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 Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
25 * USA.
26 */
27
28 #ifndef CATACOMB_OCB1_DEF_H
29 #define CATACOMB_OCB1_DEF_H
30
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34
35 /*----- Header files ------------------------------------------------------*/
36
37 #include <string.h>
38
39 #include <mLib/bits.h>
40 #include <mLib/sub.h>
41
42 #ifndef CATACOMB_ARENA_H
43 # include "arena.h"
44 #endif
45
46 #ifndef CATACOMB_BLKC_H
47 # include "blkc.h"
48 #endif
49
50 #ifndef CATACOMB_CT_H
51 # include "ct.h"
52 #endif
53
54 #ifndef CATACOMB_KEYSZ_H
55 # include "keysz.h"
56 #endif
57
58 #ifndef CATACOMB_PARANOIA_H
59 # include "paranoia.h"
60 #endif
61
62 /*----- Macros ------------------------------------------------------------*/
63
64 /* --- @OCB1_DEF@ --- *
65 *
66 * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
67 *
68 * Use: Creates an implementation for the OCB1 authenticated-
69 * encryption mode.
70 */
71
72 #define OCB1_DEF(PRE, pre) OCB1_DEFX(PRE, pre, #pre, #pre)
73
74 #define OCB1_DEFX(PRE, pre, name, fname) \
75 \
76 const octet \
77 pre##_ocb1noncesz[] = { KSZ_SET, PRE##_BLKSZ, 0 }, \
78 pre##_ocb1tagsz[] = { KSZ_RANGE, PRE##_BLKSZ, 0, PRE##_BLKSZ, 1 }; \
79 \
80 /* --- @pre_ocb1init@ --- * \
81 * \
82 * Arguments: @pre_ocb1ctx *ctx@ = pointer to OCB1 context \
83 * @const pre_ocb1key *key@ = pointer to key block \
84 * @const void *n@ = pointer to nonce \
85 * @size_t nsz@ = size of nonce \
86 * \
87 * Returns: Zero on success, @-1@ if the nonce length is bad. \
88 * \
89 * Use: Initialize an OCB1 operation context with a given key. \
90 * \
91 * The original key needn't be kept around any more. \
92 */ \
93 \
94 int pre##_ocb1init(pre##_ocb1ctx *ctx, const pre##_ocb1key *k, \
95 const void *n, size_t nsz) \
96 { ctx->k = *k; return (pre##_ocb1reinit(ctx, n, nsz)); } \
97 \
98 /* --- @pre_ocb1reinit@ --- * \
99 * \
100 * Arguments: @pre_ocb1ctx *ctx@ = pointer to OCB1 context \
101 * @const void *n@ = pointer to nonce \
102 * @size_t nsz@ = size of nonce \
103 * \
104 * Returns: Zero on success, @-1@ if the nonce length is bad. \
105 * \
106 * Use: Reinitialize an OCB1 operation context, changing the \
107 * nonce. \
108 */ \
109 \
110 int pre##_ocb1reinit(pre##_ocb1ctx *ctx, const void *n, size_t nsz) \
111 { \
112 if (nsz != PRE##_BLKSZ) return (-1); \
113 ctx->off = 0; BLKC_ZERO(PRE, ctx->a); \
114 BLKC_LOAD(PRE, ctx->o, n); BLKC_XMOVE(PRE, ctx->o, ctx->k.lmask[0]); \
115 pre##_eblk(&ctx->k.ctx, ctx->o, ctx->o); ctx->i = 1; \
116 return (0); \
117 } \
118 \
119 /* --- @pre_ocb1encrypt@ --- * \
120 * \
121 * Arguments: @pre_ocb1ctx *ctx@ = pointer to OCB1 operation context \
122 * @const void *src@ = pointer to plaintext message chunk \
123 * @size_t sz@ = size of the plaintext \
124 * @buf *dst@ = a buffer to write the ciphertext to \
125 * \
126 * Returns: Zero on success; @-1@ on failure. \
127 * \
128 * Use: Encrypts a chunk of a plaintext message, writing a \
129 * chunk of ciphertext to the output buffer and updating \
130 * the operation state. \
131 * \
132 * Note that OCB1 delays output if its input is not a \
133 * whole number of blocks. This means that the output \
134 * might be smaller or larger the input by up to the block \
135 * size. \
136 */ \
137 \
138 int pre##_ocb1encrypt(pre##_ocb1ctx *ctx, \
139 const void *src, size_t sz, buf *dst) \
140 { \
141 rsvr_state st; \
142 size_t osz; \
143 uint32 t[PRE##_BLKSZ/4]; \
144 const octet *p; \
145 octet *q; \
146 \
147 /* Figure out what we're going to do. */ \
148 rsvr_setup(&st, &pre##_ocb1policy, ctx->b, &ctx->off, src, sz); \
149 \
150 /* Determine the output size and verify that there is enough \
151 * space. \
152 */ \
153 osz = st.plan.from_rsvr + st.plan.from_input; \
154 if (!osz) q = 0; \
155 else { q = buf_get(dst, osz); if (!q) return (-1); } \
156 \
157 /* Process the input in whole blocks at a time. */ \
158 RSVR_DO(&st) while ((p = RSVR_NEXT(&st, PRE##_BLKSZ)) != 0) { \
159 OCB_OFFSET(PRE, ctx->o, ctx->k.lmask, ctx->i++); \
160 BLKC_LOAD(PRE, t, p); BLKC_XMOVE(PRE, ctx->a, t); \
161 BLKC_XMOVE(PRE, t, ctx->o); pre##_eblk(&ctx->k.ctx, t, t); \
162 BLKC_XSTORE(PRE, q, t, ctx->o); q += PRE##_BLKSZ; \
163 } \
164 \
165 /* Done. */ \
166 return (0); \
167 } \
168 \
169 /* --- @pre_ocb1decrypt@ --- * \
170 * \
171 * Arguments: @pre_ocb1ctx *ctx@ = pointer to OCB1 operation context \
172 * @const void *src@ = pointer to ciphertext message chunk \
173 * @size_t sz@ = size of the ciphertext \
174 * @buf *dst@ = a buffer to write the plaintext to \
175 * \
176 * Returns: Zero on success; @-1@ on failure. \
177 * \
178 * Use: Decrypts a chunk of a ciphertext message, writing a \
179 * chunk of plaintext to the output buffer and updating \
180 * the operation state. \
181 * \
182 * Note that OCB1 delays output if its input is not a \
183 * whole number of blocks. This means that the output \
184 * might be smaller or larger the input by up to the block \
185 * size. \
186 */ \
187 \
188 int pre##_ocb1decrypt(pre##_ocb1ctx *ctx, \
189 const void *src, size_t sz, buf *dst) \
190 { \
191 rsvr_state st; \
192 size_t osz; \
193 uint32 t[PRE##_BLKSZ/4]; \
194 const octet *p; \
195 octet *q; \
196 \
197 /* Figure out what we're going to do. */ \
198 rsvr_setup(&st, &pre##_ocb1policy, ctx->b, &ctx->off, src, sz); \
199 \
200 /* Determine the output size and verify that there is enough \
201 * space. \
202 */ \
203 osz = st.plan.from_rsvr + st.plan.from_input; \
204 if (!osz) q = 0; \
205 else { q = buf_get(dst, osz); if (!q) return (-1); } \
206 \
207 /* Process the input in whole blocks at a time. */ \
208 RSVR_DO(&st) while ((p = RSVR_NEXT(&st, PRE##_BLKSZ)) != 0) { \
209 OCB_OFFSET(PRE, ctx->o, ctx->k.lmask, ctx->i++); \
210 BLKC_LOAD(PRE, t, p); \
211 BLKC_XMOVE(PRE, t, ctx->o); pre##_dblk(&ctx->k.ctx, t, t); \
212 BLKC_XMOVE(PRE, t, ctx->o); BLKC_XMOVE(PRE, ctx->a, t); \
213 BLKC_STORE(PRE, q, t); q += PRE##_BLKSZ; \
214 } \
215 \
216 /* Done. */ \
217 return (0); \
218 } \
219 \
220 /* --- @pre_ocb1encdecfinal@ --- * \
221 * \
222 * Arguments: @pre_ocb1ctx *ctx@ = pointer to an OCB1 context \
223 * @const pre_ocb1aadctx *aad@ = pointer to AAD context, \
224 * or null \
225 * @buf *dst@ = buffer for remaining ciphertext \
226 * @int encp@ = nonzero if we're encrypting \
227 * \
228 * Returns: Zero on success; @-1@ on failure. \
229 * \
230 * Use: Common end-of-message handling for encryption and \
231 * decryption. The full-length tag is left in the \
232 * context's buffer. \
233 */ \
234 \
235 static int pre##_ocb1encdecfinal(pre##_ocb1ctx *ctx, \
236 const pre##_ocb1aadctx *aad, buf *dst, \
237 int encp) \
238 { \
239 octet *q; \
240 \
241 /* Arrange space for the final output (if any). */ \
242 if (!ctx->off) { q = 0; if (!BOK(dst)) return (-1); } \
243 else { q = buf_get(dst, ctx->off); if (!q) return (-1); } \
244 \
245 /* Calculate the final offset. Mix it into the checksum before it \
246 * gets clobbered. \
247 */ \
248 OCB_OFFSET(PRE, ctx->o, ctx->k.lmask, ctx->i++); \
249 BLKC_XMOVE(PRE, ctx->a, ctx->o); \
250 \
251 /* Mix the magic final mask and tail length into the offset. */ \
252 BLKC_XMOVE(PRE, ctx->o, ctx->k.lxinv); \
253 ctx->o[PRE##_BLKSZ/4 - 1] ^= BLKC_BWORD(PRE, 8*ctx->off); \
254 \
255 /* If we're decrypting, then trim the end of the plaintext and fold \
256 * that into the checksum. \
257 */ \
258 if (!encp) { \
259 memset(ctx->b + ctx->off, 0, PRE##_BLKSZ - ctx->off); \
260 BLKC_XLOAD(PRE, ctx->a, ctx->b); \
261 } \
262 \
263 /* Cycle the block cipher for the last plaintext block. */ \
264 pre##_eblk(&ctx->k.ctx, ctx->o, ctx->o); \
265 \
266 /* Fold this mask into the checksum before it gets clobbered. */ \
267 BLKC_XMOVE(PRE, ctx->a, ctx->o); \
268 \
269 /* Encrypt the message tail. */ \
270 BLKC_XLOAD(PRE, ctx->o, ctx->b); \
271 BLKC_STORE(PRE, ctx->b, ctx->o); \
272 if (ctx->off) memcpy(q, ctx->b, ctx->off); \
273 \
274 /* If we're encrypting, then trim the end of the ciphertext and fold \
275 * that into the checksum. \
276 */ \
277 if (encp) { \
278 memset(ctx->b + ctx->off, 0, PRE##_BLKSZ - ctx->off); \
279 BLKC_XLOAD(PRE, ctx->a, ctx->b); \
280 } \
281 \
282 /* Encrypt the checksum to produce a tag. */ \
283 pre##_eblk(&ctx->k.ctx, ctx->a, ctx->a); \
284 \
285 /* If there's AAD then mix the PMAC tag in too. */ \
286 if (aad && aad->off) \
287 { pre##_ocb1aadtag(aad, ctx->o); BLKC_XMOVE(PRE, ctx->a, ctx->o); } \
288 \
289 /* Write the final tag. */ \
290 BLKC_STORE(PRE, ctx->b, ctx->a); \
291 \
292 /* Done. */ \
293 return (0); \
294 } \
295 \
296 /* --- @pre_ocb1encryptdone@ --- * \
297 * \
298 * Arguments: @pre_ocb1ctx *ctx@ = pointer to an OCB1 context \
299 * @const pre_ocb1aadctx *aad@ = pointer to AAD context, \
300 * or null \
301 * @buf *dst@ = buffer for remaining ciphertext \
302 * @void *tag@ = where to write the tag \
303 * @size_t tsz@ = length of tag to store \
304 * \
305 * Returns: Zero on success; @-1@ on failure. \
306 * \
307 * Use: Completes an OCB1 encryption operation. The @aad@ \
308 * pointer may be null if there is no additional \
309 * authenticated data. OCB1 delays output, so this will \
310 * cause any remaining buffered plaintext to be encrypted \
311 * and written to @dst@. Anyway, the function will fail \
312 * if the output buffer is broken. \
313 */ \
314 \
315 int pre##_ocb1encryptdone(pre##_ocb1ctx *ctx, \
316 const pre##_ocb1aadctx *aad, buf *dst, \
317 void *tag, size_t tsz) \
318 { \
319 assert(tsz <= PRE##_BLKSZ); \
320 if (pre##_ocb1encdecfinal(ctx, aad, dst, 1)) return (-1); \
321 memcpy(tag, ctx->b, tsz); \
322 return (0); \
323 } \
324 \
325 /* --- @pre_ocb1decryptdone@ --- * \
326 * \
327 * Arguments: @pre_ocb1ctx *ctx@ = pointer to an OCB1 context \
328 * @const pre_ocb1aadctx *aad@ = pointer to AAD context, \
329 * or null \
330 * @buf *dst@ = buffer for remaining plaintext \
331 * @const void *tag@ = tag to verify \
332 * @size_t tsz@ = length of tag \
333 * \
334 * Returns: @+1@ for complete success; @0@ if tag verification \
335 * failed; @-1@ for other kinds of errors. \
336 * \
337 * Use: Completes an OCB1 decryption operation. The @aad@ \
338 * pointer may be null if there is no additional \
339 * authenticated data. OCB1 delays output, so this will \
340 * cause any remaining buffered ciphertext to be decrypted \
341 * and written to @dst@. Anyway, the function will fail \
342 * if the output buffer is broken. \
343 */ \
344 \
345 int pre##_ocb1decryptdone(pre##_ocb1ctx *ctx, \
346 const pre##_ocb1aadctx *aad, buf *dst, \
347 const void *tag, size_t tsz) \
348 { \
349 assert(tsz <= PRE##_BLKSZ); \
350 if (pre##_ocb1encdecfinal(ctx, aad, dst, 0)) return (-1); \
351 else if (ct_memeq(tag, ctx->b, tsz)) return (+1); \
352 else return (0); \
353 } \
354 \
355 /* --- Generic AEAD interface --- */ \
356 \
357 typedef struct gactx { \
358 gaead_aad a; \
359 pre##_ocb1aadctx aad; \
360 } gactx; \
361 \
362 static gaead_aad *gadup(const gaead_aad *a) \
363 { gactx *aad = S_CREATE(gactx); *aad = *(gactx *)a; return (&aad->a); } \
364 \
365 static void gahash(gaead_aad *a, const void *h, size_t hsz) \
366 { gactx *aad = (gactx *)a; pre##_ocb1aadhash(&aad->aad, h, hsz); } \
367 \
368 static void gadestroy(gaead_aad *a) \
369 { gactx *aad = (gactx *)a; BURN(*aad); S_DESTROY(aad); } \
370 \
371 static const gaead_aadops gaops = \
372 { &pre##_ocb1, gadup, gahash, gadestroy }; \
373 \
374 static gaead_aad *gaad(const pre##_ocb1key *k) \
375 { \
376 gactx *aad = S_CREATE(gactx); \
377 aad->a.ops = &gaops; \
378 pre##_ocb1aadinit(&aad->aad, k); \
379 return (&aad->a); \
380 } \
381 \
382 typedef struct gectx { \
383 gaead_enc e; \
384 pre##_ocb1ctx ctx; \
385 } gectx; \
386 \
387 static gaead_aad *geaad(gaead_enc *e) \
388 { gectx *enc = (gectx *)e; return (gaad(&enc->ctx.k)); } \
389 \
390 static int gereinit(gaead_enc *e, const void *n, size_t nsz, \
391 size_t hsz, size_t msz, size_t tsz) \
392 { \
393 gectx *enc = (gectx *)e; \
394 return (pre##_ocb1reinit(&enc->ctx, n, nsz)); \
395 } \
396 \
397 static int geenc(gaead_enc *e, const void *m, size_t msz, buf *b) \
398 { \
399 gectx *enc = (gectx *)e; \
400 return (pre##_ocb1encrypt(&enc->ctx, m, msz, b)); \
401 } \
402 \
403 static int gedone(gaead_enc *e, const gaead_aad *a, \
404 buf *b, void *t, size_t tsz) \
405 { \
406 gectx *enc = (gectx *)e; gactx *aad = (gactx *)a; \
407 assert(!a || a->ops == &gaops); \
408 return (pre##_ocb1encryptdone(&enc->ctx, a ? &aad->aad : 0, b, t, tsz)); \
409 } \
410 \
411 static void gedestroy(gaead_enc *e) \
412 { gectx *enc = (gectx *)e; BURN(*enc); S_DESTROY(enc); } \
413 \
414 static const gaead_encops geops = \
415 { &pre##_ocb1, geaad, gereinit, geenc, gedone, gedestroy }; \
416 \
417 typedef struct gdctx { \
418 gaead_dec d; \
419 pre##_ocb1ctx ctx; \
420 } gdctx; \
421 \
422 static gaead_aad *gdaad(gaead_dec *d) \
423 { gdctx *dec = (gdctx *)d; return (gaad(&dec->ctx.k)); } \
424 \
425 static int gdreinit(gaead_dec *d, const void *n, size_t nsz, \
426 size_t hsz, size_t csz, size_t tsz) \
427 { \
428 gdctx *dec = (gdctx *)d; \
429 return (pre##_ocb1reinit(&dec->ctx, n, nsz)); \
430 } \
431 \
432 static int gddec(gaead_dec *d, const void *c, size_t csz, buf *b) \
433 { \
434 gdctx *dec = (gdctx *)d; \
435 return (pre##_ocb1decrypt(&dec->ctx, c, csz, b)); \
436 } \
437 \
438 static int gddone(gaead_dec *d, const gaead_aad *a, \
439 buf *b, const void *t, size_t tsz) \
440 { \
441 gdctx *dec = (gdctx *)d; gactx *aad = (gactx *)a; \
442 assert(!a || a->ops == &gaops); \
443 return (pre##_ocb1decryptdone(&dec->ctx, a ? &aad->aad : 0, b, t, tsz)); \
444 } \
445 \
446 static void gddestroy(gaead_dec *d) \
447 { gdctx *dec = (gdctx *)d; BURN(*dec); S_DESTROY(dec); } \
448 \
449 static const gaead_decops gdops = \
450 { &pre##_ocb1, gdaad, gdreinit, gddec, gddone, gddestroy }; \
451 \
452 typedef struct gkctx { \
453 gaead_key k; \
454 pre##_ocb1key key; \
455 } gkctx; \
456 \
457 static gaead_aad *gkaad(const gaead_key *k) \
458 { gkctx *key = (gkctx *)k; return (gaad(&key->key)); } \
459 \
460 static gaead_enc *gkenc(const gaead_key *k, const void *n, size_t nsz, \
461 size_t hsz, size_t msz, size_t tsz) \
462 { \
463 gkctx *key = (gkctx *)k; \
464 gectx *enc = S_CREATE(gectx); \
465 \
466 enc->e.ops = &geops; \
467 if (pre##_ocb1init(&enc->ctx, &key->key, n, nsz)) \
468 { gedestroy(&enc->e); return (0); } \
469 return (&enc->e); \
470 } \
471 \
472 static gaead_dec *gkdec(const gaead_key *k, const void *n, size_t nsz, \
473 size_t hsz, size_t csz, size_t tsz) \
474 { \
475 gkctx *key = (gkctx *)k; \
476 gdctx *dec = S_CREATE(gdctx); \
477 \
478 dec->d.ops = &gdops; \
479 if (pre##_ocb1init(&dec->ctx, &key->key, n, nsz)) \
480 { gddestroy(&dec->d); return (0); } \
481 return (&dec->d); \
482 } \
483 \
484 static void gkdestroy(gaead_key *k) \
485 { gkctx *key = (gkctx *)k; BURN(*key); S_DESTROY(key); } \
486 \
487 static const gaead_keyops gkops = \
488 { &pre##_ocb1, gkaad, gkenc, gkdec, gkdestroy }; \
489 \
490 static gaead_key *gckey(const void *k, size_t ksz) \
491 { \
492 gkctx *key = S_CREATE(gkctx); \
493 key->k.ops = &gkops; \
494 pre##_ocb1setkey(&key->key, k, ksz); \
495 return (&key->k); \
496 } \
497 \
498 static int gcszok(size_t nsz, size_t hsz, size_t msz, size_t tsz) \
499 { return (gaead_szokcommon(&pre##_ocb1, nsz, hsz, msz, tsz)); } \
500 \
501 const gcaead pre##_ocb1 = { \
502 name "-ocb1", \
503 pre##_keysz, pre##_ocb1noncesz, pre##_ocb1tagsz, \
504 PRE##_BLKSZ, PRE##_BLKSZ, 0, 0, \
505 gckey, gcszok \
506 }; \
507 \
508 OCB1_TESTX(PRE, pre, name, fname)
509
510 /*----- Test rig ----------------------------------------------------------*/
511
512 #define OCB1_TEST(PRE, pre) OCB1_TESTX(PRE, pre, #pre, #pre)
513
514 /* --- @OCB1_TEST@ --- *
515 *
516 * Arguments: @PRE, pre@ = prefixes for the underlying block cipher
517 *
518 * Use: Standard test rig for OCB1 functions.
519 */
520
521 #ifdef TEST_RIG
522
523 #include <stdio.h>
524
525 #include <mLib/dstr.h>
526 #include <mLib/macros.h>
527 #include <mLib/quis.h>
528 #include <mLib/testrig.h>
529
530 #define OCB1_TESTX(PRE, pre, name, fname) \
531 \
532 static int ocb1verify(dstr *v) \
533 { \
534 pre##_ocb1key key; \
535 pre##_ocb1aadctx aad; \
536 pre##_ocb1ctx ctx; \
537 int ok = 1, win; \
538 int i; \
539 octet *p; \
540 int szs[] = { 1, 7, 192, -1, 0 }, *ip; \
541 size_t hsz, msz; \
542 dstr d = DSTR_INIT, t = DSTR_INIT; \
543 buf b; \
544 \
545 dstr_ensure(&d, v[4].len > v[3].len ? v[4].len : v[3].len); \
546 dstr_ensure(&t, v[5].len); t.len = v[5].len; \
547 \
548 pre##_ocb1setkey(&key, v[0].buf, v[0].len); \
549 \
550 for (ip = szs; *ip; ip++) { \
551 \
552 pre##_ocb1init(&ctx, &key, (octet *)v[1].buf, v[1].len); \
553 \
554 i = *ip; \
555 hsz = v[2].len; \
556 if (i == -1) i = hsz; \
557 if (i > hsz) continue; \
558 p = (octet *)v[2].buf; \
559 pre##_ocb1aadinit(&aad, &key); \
560 while (hsz) { \
561 if (i > hsz) i = hsz; \
562 pre##_ocb1aadhash(&aad, p, i); \
563 p += i; hsz -= i; \
564 } \
565 \
566 buf_init(&b, d.buf, d.sz); \
567 i = *ip; \
568 msz = v[3].len; \
569 if (i == -1) i = msz; \
570 if (i > msz) continue; \
571 p = (octet *)v[3].buf; \
572 while (msz) { \
573 if (i > msz) i = msz; \
574 if (pre##_ocb1encrypt(&ctx, p, i, &b)) { \
575 puts("!! ocb1encrypt reports failure"); \
576 goto fail_enc; \
577 } \
578 p += i; msz -= i; \
579 } \
580 \
581 if (pre##_ocb1encryptdone(&ctx, &aad, &b, (octet *)t.buf, t.len)) { \
582 puts("!! ocb1encryptdone reports failure"); \
583 goto fail_enc; \
584 } \
585 d.len = BLEN(&b); \
586 \
587 if (d.len != v[4].len || \
588 MEMCMP(d.buf, !=, v[4].buf, v[4].len) || \
589 MEMCMP(t.buf, !=, v[5].buf, v[5].len)) { \
590 fail_enc: \
591 printf("\nfail encrypt:\n\tstep = %i", *ip); \
592 fputs("\n\tkey = ", stdout); type_hex.dump(&v[0], stdout); \
593 fputs("\n\tnonce = ", stdout); type_hex.dump(&v[1], stdout); \
594 fputs("\n\theader = ", stdout); type_hex.dump(&v[2], stdout); \
595 fputs("\n\tmessage = ", stdout); type_hex.dump(&v[3], stdout); \
596 fputs("\n\texp ct = ", stdout); type_hex.dump(&v[4], stdout); \
597 fputs("\n\tcalc ct = ", stdout); type_hex.dump(&d, stdout); \
598 fputs("\n\texp tag = ", stdout); type_hex.dump(&v[5], stdout); \
599 fputs("\n\tcalc tag = ", stdout); type_hex.dump(&t, stdout); \
600 putchar('\n'); \
601 ok = 0; \
602 } \
603 \
604 pre##_ocb1init(&ctx, &key, (octet *)v[1].buf, v[1].len); \
605 \
606 buf_init(&b, d.buf, d.sz); \
607 i = *ip; \
608 msz = v[4].len; \
609 if (i == -1) i = msz; \
610 if (i > msz) continue; \
611 p = (octet *)v[4].buf; \
612 while (msz) { \
613 if (i > msz) i = msz; \
614 if (pre##_ocb1decrypt(&ctx, p, i, &b)) { \
615 puts("!! ocb1decrypt reports failure"); \
616 win = 0; goto fail_dec; \
617 } \
618 p += i; msz -= i; \
619 } \
620 \
621 win = pre##_ocb1decryptdone(&ctx, &aad, &b, \
622 (octet *)v[5].buf, v[5].len); \
623 if (win < 0) { \
624 puts("!! ocb1decryptdone reports failure"); \
625 goto fail_dec; \
626 } \
627 d.len = BLEN(&b); \
628 \
629 if (d.len != v[3].len || !win || \
630 MEMCMP(d.buf, !=, v[3].buf, v[3].len)) { \
631 fail_dec: \
632 printf("\nfail decrypt:\n\tstep = %i", *ip); \
633 fputs("\n\tkey = ", stdout); type_hex.dump(&v[0], stdout); \
634 fputs("\n\tnonce = ", stdout); type_hex.dump(&v[1], stdout); \
635 fputs("\n\theader = ", stdout); type_hex.dump(&v[2], stdout); \
636 fputs("\n\tciphertext = ", stdout); type_hex.dump(&v[4], stdout); \
637 fputs("\n\texp pt = ", stdout); type_hex.dump(&v[3], stdout); \
638 fputs("\n\tcalc pt = ", stdout); type_hex.dump(&d, stdout); \
639 fputs("\n\ttag = ", stdout); type_hex.dump(&v[5], stdout); \
640 printf("\n\tverify %s", win ? "ok" : "FAILED"); \
641 putchar('\n'); \
642 ok = 0; \
643 } \
644 } \
645 \
646 dstr_destroy(&d); dstr_destroy(&t); \
647 return (ok); \
648 } \
649 \
650 static test_chunk aeaddefs[] = { \
651 { name "-ocb1", ocb1verify, \
652 { &type_hex, &type_hex, &type_hex, &type_hex, \
653 &type_hex, &type_hex, 0 } }, \
654 { 0, 0, { 0 } } \
655 }; \
656 \
657 int main(int argc, char *argv[]) \
658 { \
659 ego(argv[0]); \
660 test_run(argc, argv, aeaddefs, SRCDIR"/t/" fname); \
661 return (0); \
662 }
663
664 #else
665 # define OCB1_TESTX(PRE, pre, name, fname)
666 #endif
667
668 /*----- That's all, folks -------------------------------------------------*/
669
670 #ifdef __cplusplus
671 }
672 #endif
673
674 #endif