chiark / gitweb /
math/t/mpx-mul4: Fix comment markers.
[catacomb] / symm / eax-def.h
1 /* -*-c-*-
2  *
3  * The EAX authenticated-encryption mode
4  *
5  * (c) 2017 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
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.
16  *
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.
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
24  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25  * MA 02111-1307, USA.
26  */
27
28 #ifndef CATACOMB_EAX_DEF_H
29 #define CATACOMB_EAX_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_CMAC_H
55 #  include "cmac.h"
56 #endif
57
58 #ifndef CATACOMB_CMAC_DEF_H
59 #  include "cmac-def.h"
60 #endif
61
62 #ifndef CATACOMB_KEYSZ_H
63 #  include "keysz.h"
64 #endif
65
66 #ifndef CATACOMB_PARANOIA_H
67 #  include "paranoia.h"
68 #endif
69
70 #ifndef CATACOMB_RSVR_H
71 #  include "rsvr.h"
72 #endif
73
74 /*----- Macros ------------------------------------------------------------*/
75
76 /* --- @EAX_DEF@ --- *
77  *
78  * Arguments:   @PRE@, @pre@ = prefixes for the underlying block cipher
79  *
80  * Use:         Creates an implementation for the EAX authenticated-
81  *              encryption mode.
82  */
83
84 #define EAX_DEF(PRE, pre) EAX_DEFX(PRE, pre, #pre, #pre)
85
86 #define EAX_DEFX(PRE, pre, name, fname)                                 \
87                                                                         \
88 OMAC_DECL(PRE, pre)                                                     \
89                                                                         \
90 const octet                                                             \
91   pre##_eaxnoncesz[] = { KSZ_ANY, PRE##_BLKSZ },                        \
92   pre##_eaxtagsz[] = { KSZ_RANGE, PRE##_BLKSZ, 0, PRE##_BLKSZ, 1 };     \
93                                                                         \
94 /* --- @pre_eaxsetkey@ --- *                                            \
95  *                                                                      \
96  * Arguments:   @pre_eaxkey *key@ = pointer to key block to fill in     \
97  *              @const void *k@ = pointer to key material               \
98  *              @size_t ksz@ = size of key material                     \
99  *                                                                      \
100  * Returns:     ---                                                     \
101  *                                                                      \
102  * Use:         Initializes an EAX key block.                           \
103  */                                                                     \
104                                                                         \
105 void pre##_eaxsetkey(pre##_eaxkey *key, const void *k, size_t ksz)      \
106 {                                                                       \
107   uint32 t[PRE##_BLKSZ/4];                                              \
108                                                                         \
109   /* Initialize the block cipher. */                                    \
110   pre##_init(&key->ctx, k, ksz);                                        \
111                                                                         \
112   /* Set up the OMAC masks. */                                          \
113   pre##_omacmasks(&key->ctx, key->m0, key->m1);                         \
114                                                                         \
115   /* Set up the OMAC tweaks.  EAX tweaks its MAC by simply stitching    \
116    * magic block-wide prefixes %$t_0$%, %$t_1$%, %$t_2$% (which are     \
117    * simply the numbers 0, 1, 2) on the front of strings.  We can       \
118    * accelerate things by caching two values for each tweak:            \
119    *                                                                    \
120    *   * %$v_i = E_K(t_i)$% is the accumulator that results from        \
121    *     pushing the tweak through the blockcipher, which we'd          \
122    *     calculate if the original message was nonempty.                \
123    *                                                                    \
124    *   * %$z_i = E_K(t_0 \xor m_0)$% is the tweak with the `full final  \
125    *     buffer' mask applied, which is the final tag for a final empty \
126    *     message. \
127    */                                                                   \
128   BLKC_BSET(PRE, t, 0); pre##_eblk(&key->ctx, t, key->v0);              \
129   BLKC_XMOVE(PRE, t, key->m0); pre##_eblk(&key->ctx, t, key->z0);       \
130   BLKC_BSET(PRE, t, 1); pre##_eblk(&key->ctx, t, key->v1);              \
131   BLKC_XMOVE(PRE, t, key->m0); pre##_eblk(&key->ctx, t, key->z1);       \
132   BLKC_BSET(PRE, t, 2); pre##_eblk(&key->ctx, t, key->v2);              \
133   BLKC_XMOVE(PRE, t, key->m0); pre##_eblk(&key->ctx, t, key->z2);       \
134 }                                                                       \
135                                                                         \
136 /* --- @pre_eaxaadinit@ --- *                                           \
137  *                                                                      \
138  * Arguments:   @pre_eaxaadctx *aad@ = pointer to AAD context           \
139  *              @const pre_eaxkey *key@ = pointer to key block          \
140  *                                                                      \
141  * Returns:     ---                                                     \
142  *                                                                      \
143  * Use:         Initializes an EAX AAD (`additional authenticated       \
144  *              data') context associated with a given key.  AAD        \
145  *              contexts can be copied and/or reused, saving time if    \
146  *              the AAD for a number of messages has a common prefix.   \
147  *                                                                      \
148  *              The @key@ doesn't need to be kept around, though        \
149  *              usually there'll at least be another copy in some EAX   \
150  *              operation context because the AAD on its own isn't much \
151  *              good.                                                   \
152  */                                                                     \
153                                                                         \
154 void pre##_eaxaadinit(pre##_eaxaadctx *aad, const pre##_eaxkey *key)    \
155   { aad->k = *key; aad->off = 0; BLKC_MOVE(PRE, aad->a, key->v1); }     \
156                                                                         \
157 /* --- @pre_eaxaadhash@ --- *                                           \
158  *                                                                      \
159  * Arguments:   @pre_eaxaadctx *aad@ = pointer to AAD context           \
160  *              @const void *p@ = pointer to AAD material               \
161  *              @size_t sz@ = length of AAD material                    \
162  *                                                                      \
163  * Returns:     ---                                                     \
164  *                                                                      \
165  * Use:         Feeds AAD into the context.                             \
166  */                                                                     \
167                                                                         \
168 void pre##_eaxaadhash(pre##_eaxaadctx *aad, const void *p, size_t sz)   \
169 {                                                                       \
170   rsvr_state st;                                                        \
171   const octet *q;                                                       \
172                                                                         \
173   rsvr_setup(&st, &pre##_omacpolicy, aad->b, &aad->off, p, sz);         \
174   RSVR_DO(&st) while ((q = RSVR_NEXT(&st, PRE##_BLKSZ)) != 0)           \
175     OMAC_BLOCK(PRE, pre, &aad->k.ctx, aad->a, q);                       \
176 }                                                                       \
177                                                                         \
178 /* --- @pre_eaxinit@ --- *                                              \
179  *                                                                      \
180  * Arguments:   @pre_eaxctx *ctx@ = pointer to EAX context              \
181  *              @const pre_eaxkey *key@ = pointer to key block          \
182  *              @const void *n@ = pointer to nonce                      \
183  *              @size_t nsz@ = size of nonce                            \
184  *                                                                      \
185  * Returns:     ---                                                     \
186  *                                                                      \
187  * Use:         Initialize an EAX operation context with a given key.   \
188  *                                                                      \
189  *              The original key needn't be kept around any more.       \
190  */                                                                     \
191                                                                         \
192 void pre##_eaxinit(pre##_eaxctx *ctx, const pre##_eaxkey *k,            \
193                    const void *n, size_t nsz)                           \
194   { ctx->k = *k; pre##_eaxreinit(ctx, n, nsz); }                        \
195                                                                         \
196 /* --- @pre_eaxreinit@ --- *                                            \
197  *                                                                      \
198  * Arguments:   @pre_eaxctx *ctx@ = pointer to EAX context              \
199  *              @const void *n@ = pointer to nonce                      \
200  *              @size_t nsz@ = size of nonce                            \
201  *                                                                      \
202  * Returns:     ---                                                     \
203  *                                                                      \
204  * Use:         Reinitialize an EAX operation context, changing the     \
205  *              nonce.                                                  \
206  */                                                                     \
207                                                                         \
208 void pre##_eaxreinit(pre##_eaxctx *ctx, const void *n, size_t nsz)      \
209 {                                                                       \
210   octet b[PRE##_BLKSZ];                                                 \
211   const octet *q = n;                                                   \
212                                                                         \
213   /* Initialize the OMAC context with the right tweak. */               \
214   BLKC_MOVE(PRE, ctx->a, ctx->k.v2);                                    \
215   ctx->off = 0;                                                         \
216                                                                         \
217   /* Calculate the initial counter from the nonce.  This is OMAC again, \
218    * but this time we know that we're starting from a clean slate and   \
219    * we have the whole input in one go, so we don't bother with the     \
220    * full reservoir machinery.                                          \
221    */                                                                   \
222   if (!nsz)                                                             \
223     BLKC_MOVE(PRE, ctx->c0, ctx->k.z0);                                 \
224   else {                                                                \
225     BLKC_MOVE(PRE, ctx->c0, ctx->k.v0);                                 \
226     while (nsz > PRE##_BLKSZ) {                                         \
227       OMAC_BLOCK(PRE, pre, &ctx->k.ctx, ctx->c0, q);                    \
228       q += PRE##_BLKSZ; nsz -= PRE##_BLKSZ;                             \
229     }                                                                   \
230     memcpy(b, q, nsz);                                                  \
231     pre##_omacdone(&ctx->k.ctx, ctx->k.m0, ctx->k.m1,                   \
232                    ctx->c0, b, nsz);                                    \
233   }                                                                     \
234                                                                         \
235   /* We must remember the initial counter for the final tag             \
236    * calculation.  (I conjecture that storing the final counter instead \
237    * would be just as secure, and require less state, but I've not      \
238    * proven this, and anyway it wouldn't interoperate.)  Copy it to     \
239    * make the working counter.                                          \
240    */                                                                   \
241   BLKC_MOVE(PRE, ctx->c, ctx->c0);                                      \
242 }                                                                       \
243                                                                         \
244 /* --- @pre_eaxencrypt@ --- *                                           \
245  *                                                                      \
246  * Arguments:   @pre_eaxctx *ctx@ = pointer to EAX operation context    \
247  *              @const void *src@ = pointer to plaintext message chunk  \
248  *              @size_t sz@ = size of the plaintext                     \
249  *              @buf *dst@ = a buffer to write the ciphertext to        \
250  *                                                                      \
251  * Returns:     Zero on success; @-1@ on failure.                       \
252  *                                                                      \
253  * Use:         Encrypts a chunk of a plaintext message, writing a      \
254  *              chunk of ciphertext to the output buffer and updating   \
255  *              the operation state.                                    \
256  *                                                                      \
257  *              For EAX, we always write a ciphertext chunk the same    \
258  *              size as the plaintext.  The messing about with @buf@    \
259  *              objects makes the interface consistent with other AEAD  \
260  *              schemes which can't do this.                            \
261  */                                                                     \
262                                                                         \
263 int pre##_eaxencrypt(pre##_eaxctx *ctx,                                 \
264                      const void *src, size_t sz, buf *dst)              \
265 {                                                                       \
266   rsvr_plan plan;                                                       \
267   uint32 t[PRE##_BLKSZ/4];                                              \
268   const octet *p = src;                                                 \
269   octet *q, *r, y;                                                      \
270                                                                         \
271   /* Allocate space for the ciphertext. */                              \
272   if (sz) { q = buf_get(dst, sz); if (!q) return (-1); }                \
273   else q = 0;                                                           \
274                                                                         \
275   /* Determine the buffering plan.  Our buffer is going to do double-   \
276    * duty here.  The end portion is going to contain mask from the      \
277    * encrypted counter which we mix into the plaintext to encrypt it;   \
278    * the start portion, which originally mask bytes we've already used, \
279    * will hold the output ciphertext, which will eventually be          \
280    * collected into the OMAC state.                                     \
281    */                                                                   \
282   rsvr_mkplan(&plan, &pre##_omacpolicy, ctx->off, sz);                  \
283                                                                         \
284   /* Initial portion, fulfilled from the buffer.  If the buffer is      \
285    * empty, then that means that we haven't yet encrypted the current   \
286    * counter, so we should do that and advance it.                      \
287    */                                                                   \
288   if (plan.head) {                                                      \
289     if (!ctx->off) {                                                    \
290       pre##_eblk(&ctx->k.ctx, ctx->c, t); BLKC_BSTEP(PRE, ctx->c);      \
291       BLKC_STORE(PRE, ctx->b, t);                                       \
292     }                                                                   \
293     r = ctx->b + ctx->off; ctx->off += plan.head;                       \
294     while (plan.head--) { y = *p++ ^ *r; *r++ = *q++ = y; }             \
295   }                                                                     \
296                                                                         \
297   /* If we've filled up the buffer then we need to cycle the MAC and    \
298    * reset the offset.                                                  \
299    */                                                                   \
300   if (plan.from_rsvr) {                                                 \
301     OMAC_BLOCK(PRE, pre, &ctx->k.ctx, ctx->a, ctx->b);                  \
302     ctx->off = 0;                                                       \
303   }                                                                     \
304                                                                         \
305   /* Now to process the main body of the input.  We sneakily open-code  \
306    * the OMAC part of this.                                             \
307    */                                                                   \
308   while (plan.from_input) {                                             \
309     pre##_eblk(&ctx->k.ctx, ctx->c, t); BLKC_BSTEP(PRE, ctx->c);        \
310     BLKC_XLOAD(PRE, t, p); p += PRE##_BLKSZ;                            \
311     BLKC_STORE(PRE, q, t); q += PRE##_BLKSZ;                            \
312     BLKC_XMOVE(PRE, ctx->a, t); pre##_eblk(&ctx->k.ctx, ctx->a, ctx->a); \
313     plan.from_input -= PRE##_BLKSZ;                                     \
314   }                                                                     \
315                                                                         \
316   /* Finally, deal with any final portion.  If there is one, we know    \
317    * that the buffer is empty: we must have filled it above, or this    \
318    * would all count as `initial' data.                                 \
319    */                                                                   \
320   if (plan.tail) {                                                      \
321     pre##_eblk(&ctx->k.ctx, ctx->c, t); BLKC_BSTEP(PRE, ctx->c);        \
322     BLKC_STORE(PRE, ctx->b, t);                                         \
323     r = ctx->b; ctx->off += plan.tail;                                  \
324     while (plan.tail--) { y = *p++ ^ *r; *r++ = *q++ = y; }             \
325   }                                                                     \
326                                                                         \
327   /* And we're done. */                                                 \
328   return (0);                                                           \
329 }                                                                       \
330                                                                         \
331 /* --- @pre_eaxdecrypt@ --- *                                           \
332  *                                                                      \
333  * Arguments:   @pre_eaxctx *ctx@ = pointer to EAX operation context    \
334  *              @const void *src@ = pointer to ciphertext message chunk \
335  *              @size_t sz@ = size of the ciphertext                    \
336  *              @buf *dst@ = a buffer to write the plaintext to         \
337  *                                                                      \
338  * Returns:     Zero on success; @-1@ on failure.                       \
339  *                                                                      \
340  * Use:         Decrypts a chunk of a ciphertext message, writing a     \
341  *              chunk of plaintext to the output buffer and updating    \
342  *              the operation state.                                    \
343  *                                                                      \
344  *              For EAX, we always write a plaintext chunk the same     \
345  *              size as the ciphertext.  The messing about with @buf@   \
346  *              objects makes the interface consistent with other AEAD  \
347  *              schemes which can't do this.                            \
348  */                                                                     \
349                                                                         \
350 int pre##_eaxdecrypt(pre##_eaxctx *ctx,                                 \
351                      const void *src, size_t sz, buf *dst)              \
352 {                                                                       \
353   rsvr_plan plan;                                                       \
354   uint32 t[PRE##_BLKSZ/4], u[PRE##_BLKSZ];                              \
355   const octet *p = src;                                                 \
356   octet *q, *r, y;                                                      \
357                                                                         \
358   /* Allocate space for the plaintext. */                               \
359   if (sz) { q = buf_get(dst, sz); if (!q) return (-1); }                \
360   else q = 0;                                                           \
361                                                                         \
362   /* Determine the buffering plan.  Our buffer is going to do double-   \
363    * duty here.  The end portion is going to contain mask from the      \
364    * encrypted counter which we mix into the plaintext to encrypt it;   \
365    * the start portion, which originally mask bytes we've already used, \
366    * will hold the input ciphertext, which will eventually be           \
367    * collected into the OMAC state.                                     \
368    */                                                                   \
369   rsvr_mkplan(&plan, &pre##_omacpolicy, ctx->off, sz);                  \
370                                                                         \
371   /* Initial portion, fulfilled from the buffer.  If the buffer is      \
372    * empty, then that means that we haven't yet encrypted the current   \
373    * counter, so we should do that and advance it.                      \
374    */                                                                   \
375   if (plan.head) {                                                      \
376     if (!ctx->off) {                                                    \
377       pre##_eblk(&ctx->k.ctx, ctx->c, t); BLKC_BSTEP(PRE, ctx->c);      \
378       BLKC_STORE(PRE, ctx->b, t);                                       \
379     }                                                                   \
380     r = ctx->b + ctx->off; ctx->off += plan.head;                       \
381     while (plan.head--) { y = *p++; *q++ = y ^ *r; *r++ = y; }          \
382   }                                                                     \
383                                                                         \
384   /* If we've filled up the buffer then we need to cycle the MAC and    \
385    * reset the offset.                                                  \
386    */                                                                   \
387   if (plan.from_rsvr) {                                                 \
388     OMAC_BLOCK(PRE, pre, &ctx->k.ctx, ctx->a, ctx->b);                  \
389     ctx->off = 0;                                                       \
390   }                                                                     \
391                                                                         \
392   /* Now to process the main body of the input.  We sneakily open-code  \
393    * the OMAC part of this.                                             \
394    */                                                                   \
395   while (plan.from_input) {                                             \
396     pre##_eblk(&ctx->k.ctx, ctx->c, t); BLKC_BSTEP(PRE, ctx->c);        \
397     BLKC_LOAD(PRE, u, p); p += PRE##_BLKSZ;                             \
398     BLKC_XSTORE(PRE, q, t, u); q += PRE##_BLKSZ;                        \
399     BLKC_XMOVE(PRE, ctx->a, u); pre##_eblk(&ctx->k.ctx, ctx->a, ctx->a); \
400     plan.from_input -= PRE##_BLKSZ;                                     \
401   }                                                                     \
402                                                                         \
403   /* Finally, deal with any final portion.  If there is one, we know    \
404    * that the buffer is empty: we must have filled it above, or this    \
405    * would all count as `initial' data.                                 \
406    */                                                                   \
407   if (plan.tail) {                                                      \
408     pre##_eblk(&ctx->k.ctx, ctx->c, t); BLKC_BSTEP(PRE, ctx->c);        \
409     BLKC_STORE(PRE, ctx->b, t);                                         \
410     r = ctx->b; ctx->off += plan.tail;                                  \
411     while (plan.tail--) { y = *p++; *q++ = y ^ *r; *r++ = y; }          \
412   }                                                                     \
413                                                                         \
414   /* And we're done. */                                                 \
415   return (0);                                                           \
416 }                                                                       \
417                                                                         \
418 /* --- @pre_eaxtag@ --- *                                               \
419  *                                                                      \
420  * Arguments:   @pre_eaxctx *ctx@ = pointer to an EAX context           \
421  *              @const pre_eaxaadctx *aad@ = pointer to AAD context, or \
422  *                      null                                            \
423  *              @octet *t@ = where to write a (full-length) tag         \
424  *                                                                      \
425  * Returns:     ---                                                     \
426  *                                                                      \
427  * Use:         Finishes an EAX operation, by calculating the tag.      \
428  */                                                                     \
429                                                                         \
430 static void pre##_eaxtag(pre##_eaxctx *ctx,                             \
431                          const pre##_eaxaadctx *aad, octet *t)          \
432 {                                                                       \
433   octet b[PRE##_BLKSZ];                                                 \
434   uint32 u[PRE##_BLKSZ/4];                                              \
435                                                                         \
436   /* Finish tagging the ciphertext.  (The buffer is empty if and only   \
437    * if there was no message, since the OMAC reservoir policy leaves    \
438    * the buffer full.)                                                  \
439    */                                                                   \
440   if (!ctx->off) BLKC_MOVE(PRE, ctx->a, ctx->k.z2);                     \
441   else pre##_omacdone(&ctx->k.ctx, ctx->k.m0, ctx->k.m1,                \
442                       ctx->a, ctx->b, ctx->off);                        \
443                                                                         \
444   /* If there's no AAD, because the pointer is null or no data was      \
445    * supplied, then use the cached empty-header tag.  Otherwise         \
446    * calculate the tag for the AAD.  Either way, mix the result into    \
447    * ctx->A, and be careful not to modify the AAD context.  (Again, the \
448    * buffer is empty if and only if there was no AAD.)                  \
449    */                                                                   \
450   if (!aad || !aad->off) BLKC_XMOVE(PRE, ctx->a, ctx->k.z1);            \
451   else {                                                                \
452     BLKC_MOVE(PRE, u, aad->a); memcpy(b, aad->b, aad->off);             \
453     pre##_omacdone(&ctx->k.ctx, ctx->k.m0, ctx->k.m1, u, b, aad->off);  \
454     BLKC_XMOVE(PRE, ctx->a, u);                                         \
455   }                                                                     \
456                                                                         \
457   /* Finally, mix in the initial counter value. */                      \
458   BLKC_XMOVE(PRE, ctx->a, ctx->c0);                                     \
459                                                                         \
460   /* We're done. */                                                     \
461   BLKC_STORE(PRE, t, ctx->a);                                           \
462 }                                                                       \
463                                                                         \
464 /* --- @pre_eaxencryptdone@ --- *                                       \
465  *                                                                      \
466  * Arguments:   @pre_eaxctx *ctx@ = pointer to an EAX context           \
467  *              @const pre_eaxaadctx *aad@ = pointer to AAD context, or \
468  *                      null                                            \
469  *              @buf *dst@ = buffer for remaining ciphertext            \
470  *              @void *tag@ = where to write the tag                    \
471  *              @size_t tsz@ = length of tag to store                   \
472  *                                                                      \
473  * Returns:     Zero on success; @-1@ on failure.                       \
474  *                                                                      \
475  * Use:         Completes an EAX encryption operation.  The @aad@       \
476  *              pointer may be null if there is no additional           \
477  *              authenticated data.  EAX doesn't buffer ciphertext, but \
478  *              the output buffer is provided anyway for consistency    \
479  *              with other AEAD schemes which don't have this property; \
480  *              the function will fail if the output buffer is broken.  \
481  */                                                                     \
482                                                                         \
483 int pre##_eaxencryptdone(pre##_eaxctx *ctx,                             \
484                          const pre##_eaxaadctx *aad, buf *dst,          \
485                          void *tag, size_t tsz)                         \
486 {                                                                       \
487   octet t[PRE##_BLKSZ];                                                 \
488                                                                         \
489   if (tsz > PRE##_BLKSZ) return (-1);                                   \
490   if (!BOK(dst)) return (-1);                                           \
491   pre##_eaxtag(ctx, aad, t); memcpy(tag, t, tsz);                       \
492   return (0);                                                           \
493 }                                                                       \
494                                                                         \
495 /* --- @pre_eaxdecryptdone@ --- *                                       \
496  *                                                                      \
497  * Arguments:   @pre_eaxctx *ctx@ = pointer to an EAX context           \
498  *              @const pre_eaxaadctx *aad@ = pointer to AAD context, or \
499  *                      null                                            \
500  *              @buf *dst@ = buffer for remaining plaintext             \
501  *              @const void *tag@ = tag to verify                       \
502  *              @size_t tsz@ = length of tag                            \
503  *                                                                      \
504  * Returns:     @+1@ for complete success; @0@ if tag verification      \
505  *              failed; @-1@ for other kinds of errors.                 \
506  *                                                                      \
507  * Use:         Completes an EAX decryption operation.  The @aad@       \
508  *              pointer may be null if there is no additional           \
509  *              authenticated data.  EAX doesn't buffer plaintext, but  \
510  *              the output buffer is provided anyway for consistency    \
511  *              with other AEAD schemes which don't have this property; \
512  *              the function will fail if the output buffer is broken.  \
513  */                                                                     \
514                                                                         \
515 int pre##_eaxdecryptdone(pre##_eaxctx *ctx,                             \
516                          const pre##_eaxaadctx *aad, buf *dst,          \
517                          const void *tag, size_t tsz)                   \
518 {                                                                       \
519   octet t[PRE##_BLKSZ];                                                 \
520                                                                         \
521   if (tsz > PRE##_BLKSZ) return (-1);                                   \
522   if (!BOK(dst)) return (-1);                                           \
523   pre##_eaxtag(ctx, aad, t);                                            \
524   if (!ct_memeq(tag, t, tsz)) return (0);                               \
525   else return (+1);                                                     \
526 }                                                                       \
527                                                                         \
528 /* --- Generic AEAD interface --- */                                    \
529                                                                         \
530 typedef struct gactx {                                                  \
531   gaead_aad a;                                                          \
532   pre##_eaxaadctx aad;                                                  \
533 } gactx;                                                                \
534                                                                         \
535                                                                         \
536 static gaead_aad *gadup(const gaead_aad *a)                             \
537   { gactx *aad = S_CREATE(gactx); *aad = *(gactx *)a; return (&aad->a); } \
538                                                                         \
539 static void gahash(gaead_aad *a, const void *h, size_t hsz)             \
540   { gactx *aad = (gactx *)a; pre##_eaxaadhash(&aad->aad, h, hsz); }     \
541                                                                         \
542 static void gadestroy(gaead_aad *a)                                     \
543   { gactx *aad = (gactx *)a; BURN(*aad); S_DESTROY(aad); }              \
544                                                                         \
545 static const gaead_aadops gaops =                                       \
546   { &pre##_eax, gadup, gahash, gadestroy };                             \
547                                                                         \
548 static gaead_aad *gaad(const pre##_eaxkey *k)                           \
549 {                                                                       \
550   gactx *aad = S_CREATE(gactx);                                         \
551   aad->a.ops = &gaops;                                                  \
552   pre##_eaxaadinit(&aad->aad, k);                                       \
553   return (&aad->a);                                                     \
554 }                                                                       \
555                                                                         \
556 typedef struct gectx {                                                  \
557   gaead_enc e;                                                          \
558   pre##_eaxctx ctx;                                                     \
559 } gectx;                                                                \
560                                                                         \
561 static gaead_aad *geaad(gaead_enc *e)                                   \
562   { gectx *enc = (gectx *)e; return (gaad(&enc->ctx.k)); }              \
563                                                                         \
564 static int gereinit(gaead_enc *e, const void *n, size_t nsz,            \
565                     size_t hsz, size_t msz, size_t tsz)                 \
566 {                                                                       \
567   gectx *enc = (gectx *)e;                                              \
568                                                                         \
569   if (tsz > PRE##_BLKSZ) return (-1);                                   \
570   pre##_eaxreinit(&enc->ctx, n, nsz);                                   \
571   return (0);                                                           \
572 }                                                                       \
573                                                                         \
574 static int geenc(gaead_enc *e, const void *m, size_t msz, buf *b)       \
575 {                                                                       \
576   gectx *enc = (gectx *)e;                                              \
577   return (pre##_eaxencrypt(&enc->ctx, m, msz, b));                      \
578 }                                                                       \
579                                                                         \
580 static int gedone(gaead_enc *e, const gaead_aad *a,                     \
581                   buf *b, void *t, size_t tsz)                          \
582 {                                                                       \
583   gectx *enc = (gectx *)e; gactx *aad = (gactx *)a;                     \
584   assert(!a || a->ops == &gaops);                                       \
585   return (pre##_eaxencryptdone(&enc->ctx, a ? &aad->aad : 0, b, t, tsz)); \
586 }                                                                       \
587                                                                         \
588 static void gedestroy(gaead_enc *e)                                     \
589   { gectx *enc = (gectx *)e; BURN(*enc); S_DESTROY(enc); }              \
590                                                                         \
591 static const gaead_encops geops =                                       \
592   { &pre##_eax, geaad, gereinit, geenc, gedone, gedestroy };            \
593                                                                         \
594 typedef struct gdctx {                                                  \
595   gaead_dec d;                                                          \
596   pre##_eaxctx ctx;                                                     \
597 } gdctx;                                                                \
598                                                                         \
599 static gaead_aad *gdaad(gaead_dec *d)                                   \
600   { gdctx *dec = (gdctx *)d; return (gaad(&dec->ctx.k)); }              \
601                                                                         \
602 static int gdreinit(gaead_dec *d, const void *n, size_t nsz,            \
603                     size_t hsz, size_t csz, size_t tsz)                 \
604 {                                                                       \
605   gdctx *dec = (gdctx *)d;                                              \
606                                                                         \
607   if (tsz > PRE##_BLKSZ) return (-1);                                   \
608   pre##_eaxreinit(&dec->ctx, n, nsz);                                   \
609   return (0);                                                           \
610 }                                                                       \
611                                                                         \
612 static int gddec(gaead_dec *d, const void *c, size_t csz, buf *b)       \
613 {                                                                       \
614   gdctx *dec = (gdctx *)d;                                              \
615   return (pre##_eaxdecrypt(&dec->ctx, c, csz, b));                      \
616 }                                                                       \
617                                                                         \
618 static int gddone(gaead_dec *d, const gaead_aad *a,                     \
619                   buf *b, const void *t, size_t tsz)                    \
620 {                                                                       \
621   gdctx *dec = (gdctx *)d; gactx *aad = (gactx *)a;                     \
622   assert(!a || a->ops == &gaops);                                       \
623   return (pre##_eaxdecryptdone(&dec->ctx, a ? &aad->aad : 0, b, t, tsz)); \
624 }                                                                       \
625                                                                         \
626 static void gddestroy(gaead_dec *d)                                     \
627   { gdctx *dec = (gdctx *)d; BURN(*dec); S_DESTROY(dec); }              \
628                                                                         \
629 static const gaead_decops gdops =                                       \
630   { &pre##_eax, gdaad, gdreinit, gddec, gddone, gddestroy };            \
631                                                                         \
632 typedef struct gkctx {                                                  \
633   gaead_key k;                                                          \
634   pre##_eaxkey key;                                                     \
635 } gkctx;                                                                \
636                                                                         \
637 static gaead_aad *gkaad(const gaead_key *k)                             \
638   { gkctx *key = (gkctx *)k; return (gaad(&key->key)); }                \
639                                                                         \
640 static gaead_enc *gkenc(const gaead_key *k, const void *n, size_t nsz,  \
641                         size_t hsz, size_t msz, size_t tsz)             \
642 {                                                                       \
643   gkctx *key = (gkctx *)k;                                              \
644   gectx *enc;                                                           \
645                                                                         \
646   if (tsz > PRE##_BLKSZ) return (0);                                    \
647   enc = S_CREATE(gectx); enc->e.ops = &geops;                           \
648   pre##_eaxinit(&enc->ctx, &key->key, n, nsz);                          \
649   return (&enc->e);                                                     \
650 }                                                                       \
651                                                                         \
652 static gaead_dec *gkdec(const gaead_key *k, const void *n, size_t nsz,  \
653                         size_t hsz, size_t csz, size_t tsz)             \
654 {                                                                       \
655   gkctx *key = (gkctx *)k;                                              \
656   gdctx *dec;                                                           \
657                                                                         \
658   if (tsz > PRE##_BLKSZ) return (0);                                    \
659   dec = S_CREATE(gdctx); dec->d.ops = &gdops;                           \
660   pre##_eaxinit(&dec->ctx, &key->key, n, nsz);                          \
661   return (&dec->d);                                                     \
662 }                                                                       \
663                                                                         \
664 static void gkdestroy(gaead_key *k)                                     \
665   { gkctx *key = (gkctx *)k; BURN(*key); S_DESTROY(key); }              \
666                                                                         \
667 static const gaead_keyops gkops =                                       \
668   { &pre##_eax, gkaad, gkenc, gkdec, gkdestroy };                       \
669                                                                         \
670 static gaead_key *gckey(const void *k, size_t ksz)                      \
671 {                                                                       \
672   gkctx *key = S_CREATE(gkctx);                                         \
673   key->k.ops = &gkops;                                                  \
674   pre##_eaxsetkey(&key->key, k, ksz);                                   \
675   return (&key->k);                                                     \
676 }                                                                       \
677                                                                         \
678 const gcaead pre##_eax = {                                              \
679   name "-eax",                                                          \
680   pre##_keysz, pre##_eaxnoncesz, pre##_eaxtagsz,                        \
681   PRE##_BLKSZ, 0, 0, 0,                                                 \
682   gckey                                                                 \
683 };                                                                      \
684                                                                         \
685 EAX_TESTX(PRE, pre, name, fname)
686
687 /*----- Test rig ----------------------------------------------------------*/
688
689 #define EAX_TEST(PRE, pre) EAX_TESTX(PRE, pre, #pre, #pre)
690
691 /* --- @EAX_TEST@ --- *
692  *
693  * Arguments:   @PRE, pre@ = prefixes for the underlying block cipher
694  *
695  * Use:         Standard test rig for EAX functions.
696  */
697
698 #ifdef TEST_RIG
699
700 #include <stdio.h>
701
702 #include <mLib/dstr.h>
703 #include <mLib/macros.h>
704 #include <mLib/quis.h>
705 #include <mLib/testrig.h>
706
707 #define EAX_TESTX(PRE, pre, name, fname)                                \
708                                                                         \
709 static int eaxverify(dstr *v)                                           \
710 {                                                                       \
711   pre##_eaxkey key;                                                     \
712   pre##_eaxaadctx aad;                                                  \
713   pre##_eaxctx ctx;                                                     \
714   int ok = 1, win;                                                      \
715   int i;                                                                \
716   octet *p;                                                             \
717   int szs[] = { 1, 7, 192, -1, 0 }, *ip;                                \
718   size_t hsz, msz;                                                      \
719   dstr d = DSTR_INIT, t = DSTR_INIT;                                    \
720   buf b;                                                                \
721                                                                         \
722   dstr_ensure(&d, v[4].len > v[3].len ? v[4].len : v[3].len);           \
723   dstr_ensure(&t, v[5].len); t.len = v[5].len;                          \
724                                                                         \
725   pre##_eaxsetkey(&key, v[0].buf, v[0].len);                            \
726                                                                         \
727   for (ip = szs; *ip; ip++) {                                           \
728                                                                         \
729     pre##_eaxinit(&ctx, &key, (octet *)v[1].buf, v[1].len);             \
730                                                                         \
731     i = *ip;                                                            \
732     hsz = v[2].len;                                                     \
733     if (i == -1) i = hsz;                                               \
734     if (i > hsz) continue;                                              \
735     p = (octet *)v[2].buf;                                              \
736     pre##_eaxaadinit(&aad, &key);                                       \
737     while (hsz) {                                                       \
738       if (i > hsz) i = hsz;                                             \
739       pre##_eaxaadhash(&aad, p, i);                                     \
740       p += i; hsz -= i;                                                 \
741     }                                                                   \
742                                                                         \
743     buf_init(&b, d.buf, d.sz);                                          \
744     i = *ip;                                                            \
745     msz = v[3].len;                                                     \
746     if (i == -1) i = msz;                                               \
747     if (i > msz) continue;                                              \
748     p = (octet *)v[3].buf;                                              \
749     while (msz) {                                                       \
750       if (i > msz) i = msz;                                             \
751       if (pre##_eaxencrypt(&ctx, p, i, &b)) {                           \
752         puts("!! eaxencrypt reports failure");                          \
753         goto fail_enc;                                                  \
754       }                                                                 \
755       p += i; msz -= i;                                                 \
756     }                                                                   \
757                                                                         \
758     if (pre##_eaxencryptdone(&ctx, &aad, &b, (octet *)t.buf, t.len)) {  \
759       puts("!! eaxencryptdone reports failure");                        \
760       goto fail_enc;                                                    \
761     }                                                                   \
762     d.len = BLEN(&b);                                                   \
763                                                                         \
764     if (d.len != v[4].len ||                                            \
765         MEMCMP(d.buf, !=, v[4].buf, v[4].len) ||                        \
766         MEMCMP(t.buf, !=, v[5].buf, v[5].len)) {                        \
767     fail_enc:                                                           \
768       printf("\nfail encrypt:\n\tstep = %i", *ip);                      \
769       fputs("\n\tkey = ", stdout); type_hex.dump(&v[0], stdout);        \
770       fputs("\n\tnonce = ", stdout); type_hex.dump(&v[1], stdout);      \
771       fputs("\n\theader = ", stdout); type_hex.dump(&v[2], stdout);     \
772       fputs("\n\tmessage = ", stdout); type_hex.dump(&v[3], stdout);    \
773       fputs("\n\texp ct = ", stdout); type_hex.dump(&v[4], stdout);     \
774       fputs("\n\tcalc ct = ", stdout); type_hex.dump(&d, stdout);       \
775       fputs("\n\texp tag = ", stdout); type_hex.dump(&v[5], stdout);    \
776       fputs("\n\tcalc tag = ", stdout); type_hex.dump(&t, stdout);      \
777       putchar('\n');                                                    \
778       ok = 0;                                                           \
779     }                                                                   \
780                                                                         \
781     pre##_eaxinit(&ctx, &key, (octet *)v[1].buf, v[1].len);             \
782                                                                         \
783     buf_init(&b, d.buf, d.sz);                                          \
784     i = *ip;                                                            \
785     msz = v[4].len;                                                     \
786     if (i == -1) i = msz;                                               \
787     if (i > msz) continue;                                              \
788     p = (octet *)v[4].buf;                                              \
789     while (msz) {                                                       \
790       if (i > msz) i = msz;                                             \
791       if (pre##_eaxdecrypt(&ctx, p, i, &b)) {                           \
792         puts("!! eaxdecrypt reports failure");                          \
793         win = 0; goto fail_dec;                                         \
794       }                                                                 \
795       p += i; msz -= i;                                                 \
796     }                                                                   \
797                                                                         \
798     win = pre##_eaxdecryptdone(&ctx, &aad, &b,                          \
799                                (octet *)v[5].buf, v[5].len);            \
800     if (win < 0) {                                                      \
801       puts("!! eaxdecryptdone reports failure");                        \
802       goto fail_dec;                                                    \
803     }                                                                   \
804     d.len = BLEN(&b);                                                   \
805                                                                         \
806     if (d.len != v[3].len || !win ||                                    \
807         MEMCMP(d.buf, !=, v[3].buf, v[3].len)) {                        \
808     fail_dec:                                                           \
809       printf("\nfail decrypt:\n\tstep = %i", *ip);                      \
810       fputs("\n\tkey = ", stdout); type_hex.dump(&v[0], stdout);        \
811       fputs("\n\tnonce = ", stdout); type_hex.dump(&v[1], stdout);      \
812       fputs("\n\theader = ", stdout); type_hex.dump(&v[2], stdout);     \
813       fputs("\n\tciphertext = ", stdout); type_hex.dump(&v[4], stdout); \
814       fputs("\n\texp pt = ", stdout); type_hex.dump(&v[3], stdout);     \
815       fputs("\n\tcalc pt = ", stdout); type_hex.dump(&d, stdout);       \
816       fputs("\n\ttag = ", stdout); type_hex.dump(&v[5], stdout);        \
817       printf("\n\tverify %s", win ? "ok" : "FAILED");                   \
818       putchar('\n');                                                    \
819       ok = 0;                                                           \
820     }                                                                   \
821   }                                                                     \
822                                                                         \
823   dstr_destroy(&d); dstr_destroy(&t);                                   \
824   return (ok);                                                          \
825 }                                                                       \
826                                                                         \
827 static test_chunk aeaddefs[] = {                                        \
828   { name "-eax", eaxverify,                                             \
829     { &type_hex, &type_hex, &type_hex, &type_hex,                       \
830       &type_hex, &type_hex, 0 } },                                      \
831   { 0, 0, { 0 } }                                                       \
832 };                                                                      \
833                                                                         \
834 int main(int argc, char *argv[])                                        \
835 {                                                                       \
836   ego(argv[0]);                                                         \
837   test_run(argc, argv, aeaddefs, SRCDIR"/t/" fname);                    \
838   return (0);                                                           \
839 }
840
841 #else
842 #  define EAX_TESTX(PRE, pre, name, fname)
843 #endif
844
845 /*----- That's all, folks -------------------------------------------------*/
846
847 #ifdef __cplusplus
848   }
849 #endif
850
851 #endif