chiark / gitweb /
Merge branch '2.4.x' into 2.5.x
[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 const gcaead pre##_ocb1 = {                                             \
499   name "-ocb1",                                                         \
500   pre##_keysz, pre##_ocb1noncesz, pre##_ocb1tagsz,                      \
501   PRE##_BLKSZ, PRE##_BLKSZ, 0, 0,                                       \
502   gckey                                                                 \
503 };                                                                      \
504                                                                         \
505 OCB1_TESTX(PRE, pre, name, fname)
506
507 /*----- Test rig ----------------------------------------------------------*/
508
509 #define OCB1_TEST(PRE, pre) OCB1_TESTX(PRE, pre, #pre, #pre)
510
511 /* --- @OCB1_TEST@ --- *
512  *
513  * Arguments:   @PRE, pre@ = prefixes for the underlying block cipher
514  *
515  * Use:         Standard test rig for OCB1 functions.
516  */
517
518 #ifdef TEST_RIG
519
520 #include <stdio.h>
521
522 #include <mLib/dstr.h>
523 #include <mLib/quis.h>
524 #include <mLib/testrig.h>
525
526 #define OCB1_TESTX(PRE, pre, name, fname)                               \
527                                                                         \
528 static int ocb1verify(dstr *v)                                          \
529 {                                                                       \
530   pre##_ocb1key key;                                                    \
531   pre##_ocb1aadctx aad;                                                 \
532   pre##_ocb1ctx ctx;                                                    \
533   int ok = 1, win;                                                      \
534   int i;                                                                \
535   octet *p;                                                             \
536   int szs[] = { 1, 7, 192, -1, 0 }, *ip;                                \
537   size_t hsz, msz;                                                      \
538   dstr d = DSTR_INIT, t = DSTR_INIT;                                    \
539   buf b;                                                                \
540                                                                         \
541   dstr_ensure(&d, v[4].len > v[3].len ? v[4].len : v[3].len);           \
542   dstr_ensure(&t, v[5].len); t.len = v[5].len;                          \
543                                                                         \
544   pre##_ocb1setkey(&key, v[0].buf, v[0].len);                           \
545                                                                         \
546   for (ip = szs; *ip; ip++) {                                           \
547                                                                         \
548     pre##_ocb1init(&ctx, &key, (octet *)v[1].buf, v[1].len);            \
549                                                                         \
550     i = *ip;                                                            \
551     hsz = v[2].len;                                                     \
552     if (i == -1) i = hsz;                                               \
553     if (i > hsz) continue;                                              \
554     p = (octet *)v[2].buf;                                              \
555     pre##_ocb1aadinit(&aad, &key);                                      \
556     while (hsz) {                                                       \
557       if (i > hsz) i = hsz;                                             \
558       pre##_ocb1aadhash(&aad, p, i);                                    \
559       p += i; hsz -= i;                                                 \
560     }                                                                   \
561                                                                         \
562     buf_init(&b, d.buf, d.sz);                                          \
563     i = *ip;                                                            \
564     msz = v[3].len;                                                     \
565     if (i == -1) i = msz;                                               \
566     if (i > msz) continue;                                              \
567     p = (octet *)v[3].buf;                                              \
568     while (msz) {                                                       \
569       if (i > msz) i = msz;                                             \
570       if (pre##_ocb1encrypt(&ctx, p, i, &b)) {                          \
571         puts("!! ocb1encrypt reports failure");                         \
572         goto fail_enc;                                                  \
573       }                                                                 \
574       p += i; msz -= i;                                                 \
575     }                                                                   \
576                                                                         \
577     if (pre##_ocb1encryptdone(&ctx, &aad, &b, (octet *)t.buf, t.len)) { \
578       puts("!! ocb1encryptdone reports failure");                       \
579       goto fail_enc;                                                    \
580     }                                                                   \
581     d.len = BLEN(&b);                                                   \
582                                                                         \
583     if (d.len != v[4].len ||                                            \
584         memcmp(d.buf, v[4].buf, v[4].len) != 0 ||                       \
585         memcmp(t.buf, v[5].buf, v[5].len) != 0) {                       \
586     fail_enc:                                                           \
587       printf("\nfail encrypt:\n\tstep = %i", *ip);                      \
588       fputs("\n\tkey = ", stdout); type_hex.dump(&v[0], stdout);        \
589       fputs("\n\tnonce = ", stdout); type_hex.dump(&v[1], stdout);      \
590       fputs("\n\theader = ", stdout); type_hex.dump(&v[2], stdout);     \
591       fputs("\n\tmessage = ", stdout); type_hex.dump(&v[3], stdout);    \
592       fputs("\n\texp ct = ", stdout); type_hex.dump(&v[4], stdout);     \
593       fputs("\n\tcalc ct = ", stdout); type_hex.dump(&d, stdout);       \
594       fputs("\n\texp tag = ", stdout); type_hex.dump(&v[5], stdout);    \
595       fputs("\n\tcalc tag = ", stdout); type_hex.dump(&t, stdout);      \
596       putchar('\n');                                                    \
597       ok = 0;                                                           \
598     }                                                                   \
599                                                                         \
600     pre##_ocb1init(&ctx, &key, (octet *)v[1].buf, v[1].len);            \
601                                                                         \
602     buf_init(&b, d.buf, d.sz);                                          \
603     i = *ip;                                                            \
604     msz = v[4].len;                                                     \
605     if (i == -1) i = msz;                                               \
606     if (i > msz) continue;                                              \
607     p = (octet *)v[4].buf;                                              \
608     while (msz) {                                                       \
609       if (i > msz) i = msz;                                             \
610       if (pre##_ocb1decrypt(&ctx, p, i, &b)) {                          \
611         puts("!! ocb1decrypt reports failure");                         \
612         win = 0; goto fail_dec;                                         \
613       }                                                                 \
614       p += i; msz -= i;                                                 \
615     }                                                                   \
616                                                                         \
617     win = pre##_ocb1decryptdone(&ctx, &aad, &b,                         \
618                                (octet *)v[5].buf, v[5].len);            \
619     if (win < 0) {                                                      \
620       puts("!! ocb1decryptdone reports failure");                       \
621       goto fail_dec;                                                    \
622     }                                                                   \
623     d.len = BLEN(&b);                                                   \
624                                                                         \
625     if (d.len != v[3].len || !win ||                                    \
626         memcmp(d.buf, v[3].buf, v[3].len) != 0) {                       \
627     fail_dec:                                                           \
628       printf("\nfail decrypt:\n\tstep = %i", *ip);                      \
629       fputs("\n\tkey = ", stdout); type_hex.dump(&v[0], stdout);        \
630       fputs("\n\tnonce = ", stdout); type_hex.dump(&v[1], stdout);      \
631       fputs("\n\theader = ", stdout); type_hex.dump(&v[2], stdout);     \
632       fputs("\n\tciphertext = ", stdout); type_hex.dump(&v[4], stdout); \
633       fputs("\n\texp pt = ", stdout); type_hex.dump(&v[3], stdout);     \
634       fputs("\n\tcalc pt = ", stdout); type_hex.dump(&d, stdout);       \
635       fputs("\n\ttag = ", stdout); type_hex.dump(&v[5], stdout);        \
636       printf("\n\tverify %s", win ? "ok" : "FAILED");                   \
637       putchar('\n');                                                    \
638       ok = 0;                                                           \
639     }                                                                   \
640   }                                                                     \
641                                                                         \
642   dstr_destroy(&d); dstr_destroy(&t);                                   \
643   return (ok);                                                          \
644 }                                                                       \
645                                                                         \
646 static test_chunk aeaddefs[] = {                                        \
647   { name "-ocb1", ocb1verify,                                           \
648     { &type_hex, &type_hex, &type_hex, &type_hex,                       \
649       &type_hex, &type_hex, 0 } },                                      \
650   { 0, 0, { 0 } }                                                       \
651 };                                                                      \
652                                                                         \
653 int main(int argc, char *argv[])                                        \
654 {                                                                       \
655   ego(argv[0]);                                                         \
656   test_run(argc, argv, aeaddefs, SRCDIR"/t/" fname);                    \
657   return (0);                                                           \
658 }
659
660 #else
661 #  define OCB1_TESTX(PRE, pre, name, fname)
662 #endif
663
664 /*----- That's all, folks -------------------------------------------------*/
665
666 #ifdef __cplusplus
667   }
668 #endif
669
670 #endif