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