progs/perftest.c: Use from Glibc syscall numbers.
[catacomb] / symm / eax-def.h
CommitLineData
2964c388
MW
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 \
88OMAC_DECL(PRE, pre) \
89 \
90const 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 \
105void 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 \
98da6142 126 * message. \
2964c388
MW
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 \
154void 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 \
168void 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 \
192void 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 \
208void 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 \
263int 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; \
799e63b4
MW
278 * the start portion, which originally contained mask bytes we've \
279 * already used, will hold the output ciphertext, which will \
280 * eventually be collected into the OMAC state. \
2964c388
MW
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 \
350int 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; \
799e63b4
MW
365 * the start portion, which originally contained mask bytes we've \
366 * already used, will hold the input ciphertext, which will \
367 * eventually be collected into the OMAC state. \
2964c388
MW
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 \
430static 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 \
483int 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 \
515int 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 \
530typedef struct gactx { \
531 gaead_aad a; \
532 pre##_eaxaadctx aad; \
533} gactx; \
534 \
535 \
536static gaead_aad *gadup(const gaead_aad *a) \
537 { gactx *aad = S_CREATE(gactx); *aad = *(gactx *)a; return (&aad->a); } \
538 \
539static void gahash(gaead_aad *a, const void *h, size_t hsz) \
540 { gactx *aad = (gactx *)a; pre##_eaxaadhash(&aad->aad, h, hsz); } \
541 \
542static void gadestroy(gaead_aad *a) \
543 { gactx *aad = (gactx *)a; BURN(*aad); S_DESTROY(aad); } \
544 \
545static const gaead_aadops gaops = \
546 { &pre##_eax, gadup, gahash, gadestroy }; \
547 \
548static 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 \
556typedef struct gectx { \
557 gaead_enc e; \
558 pre##_eaxctx ctx; \
559} gectx; \
560 \
561static gaead_aad *geaad(gaead_enc *e) \
562 { gectx *enc = (gectx *)e; return (gaad(&enc->ctx.k)); } \
563 \
564static 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 \
574static 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 \
580static 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 \
588static void gedestroy(gaead_enc *e) \
589 { gectx *enc = (gectx *)e; BURN(*enc); S_DESTROY(enc); } \
590 \
591static const gaead_encops geops = \
592 { &pre##_eax, geaad, gereinit, geenc, gedone, gedestroy }; \
593 \
594typedef struct gdctx { \
595 gaead_dec d; \
596 pre##_eaxctx ctx; \
597} gdctx; \
598 \
599static gaead_aad *gdaad(gaead_dec *d) \
600 { gdctx *dec = (gdctx *)d; return (gaad(&dec->ctx.k)); } \
601 \
602static 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 \
612static 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 \
618static 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 \
626static void gddestroy(gaead_dec *d) \
627 { gdctx *dec = (gdctx *)d; BURN(*dec); S_DESTROY(dec); } \
628 \
629static const gaead_decops gdops = \
630 { &pre##_eax, gdaad, gdreinit, gddec, gddone, gddestroy }; \
631 \
632typedef struct gkctx { \
633 gaead_key k; \
634 pre##_eaxkey key; \
635} gkctx; \
636 \
637static gaead_aad *gkaad(const gaead_key *k) \
638 { gkctx *key = (gkctx *)k; return (gaad(&key->key)); } \
639 \
640static 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 \
652static 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 \
664static void gkdestroy(gaead_key *k) \
665 { gkctx *key = (gkctx *)k; BURN(*key); S_DESTROY(key); } \
666 \
667static const gaead_keyops gkops = \
668 { &pre##_eax, gkaad, gkenc, gkdec, gkdestroy }; \
669 \
670static 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 \
1491bf9e
MW
678static int gcszok(size_t nsz, size_t hsz, size_t msz, size_t tsz) \
679 { return (gaead_szokcommon(&pre##_eax, nsz, hsz, msz, tsz)); } \
680 \
2964c388
MW
681const gcaead pre##_eax = { \
682 name "-eax", \
683 pre##_keysz, pre##_eaxnoncesz, pre##_eaxtagsz, \
684 PRE##_BLKSZ, 0, 0, 0, \
1491bf9e 685 gckey, gcszok \
2964c388
MW
686}; \
687 \
688EAX_TESTX(PRE, pre, name, fname)
689
690/*----- Test rig ----------------------------------------------------------*/
691
692#define EAX_TEST(PRE, pre) EAX_TESTX(PRE, pre, #pre, #pre)
693
694/* --- @EAX_TEST@ --- *
695 *
696 * Arguments: @PRE, pre@ = prefixes for the underlying block cipher
697 *
698 * Use: Standard test rig for EAX functions.
699 */
700
701#ifdef TEST_RIG
702
703#include <stdio.h>
704
705#include <mLib/dstr.h>
141c1284 706#include <mLib/macros.h>
2964c388
MW
707#include <mLib/quis.h>
708#include <mLib/testrig.h>
709
710#define EAX_TESTX(PRE, pre, name, fname) \
711 \
712static int eaxverify(dstr *v) \
713{ \
714 pre##_eaxkey key; \
715 pre##_eaxaadctx aad; \
716 pre##_eaxctx ctx; \
717 int ok = 1, win; \
718 int i; \
719 octet *p; \
720 int szs[] = { 1, 7, 192, -1, 0 }, *ip; \
721 size_t hsz, msz; \
722 dstr d = DSTR_INIT, t = DSTR_INIT; \
723 buf b; \
724 \
725 dstr_ensure(&d, v[4].len > v[3].len ? v[4].len : v[3].len); \
726 dstr_ensure(&t, v[5].len); t.len = v[5].len; \
727 \
728 pre##_eaxsetkey(&key, v[0].buf, v[0].len); \
729 \
730 for (ip = szs; *ip; ip++) { \
731 \
732 pre##_eaxinit(&ctx, &key, (octet *)v[1].buf, v[1].len); \
733 \
734 i = *ip; \
735 hsz = v[2].len; \
736 if (i == -1) i = hsz; \
737 if (i > hsz) continue; \
738 p = (octet *)v[2].buf; \
739 pre##_eaxaadinit(&aad, &key); \
740 while (hsz) { \
741 if (i > hsz) i = hsz; \
742 pre##_eaxaadhash(&aad, p, i); \
743 p += i; hsz -= i; \
744 } \
745 \
746 buf_init(&b, d.buf, d.sz); \
747 i = *ip; \
748 msz = v[3].len; \
749 if (i == -1) i = msz; \
750 if (i > msz) continue; \
751 p = (octet *)v[3].buf; \
752 while (msz) { \
753 if (i > msz) i = msz; \
754 if (pre##_eaxencrypt(&ctx, p, i, &b)) { \
755 puts("!! eaxencrypt reports failure"); \
756 goto fail_enc; \
757 } \
758 p += i; msz -= i; \
759 } \
760 \
761 if (pre##_eaxencryptdone(&ctx, &aad, &b, (octet *)t.buf, t.len)) { \
762 puts("!! eaxencryptdone reports failure"); \
763 goto fail_enc; \
764 } \
765 d.len = BLEN(&b); \
766 \
767 if (d.len != v[4].len || \
141c1284
MW
768 MEMCMP(d.buf, !=, v[4].buf, v[4].len) || \
769 MEMCMP(t.buf, !=, v[5].buf, v[5].len)) { \
2964c388
MW
770 fail_enc: \
771 printf("\nfail encrypt:\n\tstep = %i", *ip); \
772 fputs("\n\tkey = ", stdout); type_hex.dump(&v[0], stdout); \
773 fputs("\n\tnonce = ", stdout); type_hex.dump(&v[1], stdout); \
774 fputs("\n\theader = ", stdout); type_hex.dump(&v[2], stdout); \
775 fputs("\n\tmessage = ", stdout); type_hex.dump(&v[3], stdout); \
776 fputs("\n\texp ct = ", stdout); type_hex.dump(&v[4], stdout); \
777 fputs("\n\tcalc ct = ", stdout); type_hex.dump(&d, stdout); \
778 fputs("\n\texp tag = ", stdout); type_hex.dump(&v[5], stdout); \
779 fputs("\n\tcalc tag = ", stdout); type_hex.dump(&t, stdout); \
780 putchar('\n'); \
781 ok = 0; \
782 } \
783 \
784 pre##_eaxinit(&ctx, &key, (octet *)v[1].buf, v[1].len); \
785 \
786 buf_init(&b, d.buf, d.sz); \
787 i = *ip; \
788 msz = v[4].len; \
789 if (i == -1) i = msz; \
790 if (i > msz) continue; \
791 p = (octet *)v[4].buf; \
792 while (msz) { \
793 if (i > msz) i = msz; \
794 if (pre##_eaxdecrypt(&ctx, p, i, &b)) { \
795 puts("!! eaxdecrypt reports failure"); \
796 win = 0; goto fail_dec; \
797 } \
798 p += i; msz -= i; \
799 } \
800 \
801 win = pre##_eaxdecryptdone(&ctx, &aad, &b, \
802 (octet *)v[5].buf, v[5].len); \
803 if (win < 0) { \
804 puts("!! eaxdecryptdone reports failure"); \
805 goto fail_dec; \
806 } \
807 d.len = BLEN(&b); \
808 \
809 if (d.len != v[3].len || !win || \
141c1284 810 MEMCMP(d.buf, !=, v[3].buf, v[3].len)) { \
2964c388
MW
811 fail_dec: \
812 printf("\nfail decrypt:\n\tstep = %i", *ip); \
813 fputs("\n\tkey = ", stdout); type_hex.dump(&v[0], stdout); \
814 fputs("\n\tnonce = ", stdout); type_hex.dump(&v[1], stdout); \
815 fputs("\n\theader = ", stdout); type_hex.dump(&v[2], stdout); \
816 fputs("\n\tciphertext = ", stdout); type_hex.dump(&v[4], stdout); \
817 fputs("\n\texp pt = ", stdout); type_hex.dump(&v[3], stdout); \
818 fputs("\n\tcalc pt = ", stdout); type_hex.dump(&d, stdout); \
819 fputs("\n\ttag = ", stdout); type_hex.dump(&v[5], stdout); \
820 printf("\n\tverify %s", win ? "ok" : "FAILED"); \
821 putchar('\n'); \
822 ok = 0; \
823 } \
824 } \
825 \
826 dstr_destroy(&d); dstr_destroy(&t); \
827 return (ok); \
828} \
829 \
830static test_chunk aeaddefs[] = { \
831 { name "-eax", eaxverify, \
832 { &type_hex, &type_hex, &type_hex, &type_hex, \
833 &type_hex, &type_hex, 0 } }, \
834 { 0, 0, { 0 } } \
835}; \
836 \
837int main(int argc, char *argv[]) \
838{ \
839 ego(argv[0]); \
840 test_run(argc, argv, aeaddefs, SRCDIR"/t/" fname); \
841 return (0); \
842}
843
844#else
845# define EAX_TESTX(PRE, pre, name, fname)
846#endif
847
848/*----- That's all, folks -------------------------------------------------*/
849
850#ifdef __cplusplus
851 }
852#endif
853
854#endif