File Coverage

src/aead/eax.c
Criterion Covered Total %
statement 0 178 0.0
branch 0 56 0.0
condition n/a
subroutine n/a
pod n/a
total 0 234 0.0


line stmt bran cond sub pod time code
1             /*
2             * Copyright (c) 2017 Thomas Pornin
3             *
4             * Permission is hereby granted, free of charge, to any person obtaining
5             * a copy of this software and associated documentation files (the
6             * "Software"), to deal in the Software without restriction, including
7             * without limitation the rights to use, copy, modify, merge, publish,
8             * distribute, sublicense, and/or sell copies of the Software, and to
9             * permit persons to whom the Software is furnished to do so, subject to
10             * the following conditions:
11             *
12             * The above copyright notice and this permission notice shall be
13             * included in all copies or substantial portions of the Software.
14             *
15             * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16             * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17             * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18             * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19             * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20             * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21             * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22             * SOFTWARE.
23             */
24              
25             #include "inner.h"
26              
27             /*
28             * Implementation Notes
29             * ====================
30             *
31             * The combined CTR + CBC-MAC functions can only handle full blocks,
32             * so some buffering is necessary. Moreover, EAX has a special padding
33             * rule for CBC-MAC, which implies that we cannot compute the MAC over
34             * the last received full block until we know whether we are at the
35             * end of the data or not.
36             *
37             * - 'ptr' contains a value from 1 to 16, which is the number of bytes
38             * accumulated in buf[] that still needs to be processed with the
39             * current OMAC computation. Beware that this can go to 16: a
40             * complete block cannot be processed until it is known whether it
41             * is the last block or not. However, it can never be 0, because
42             * OMAC^t works on an input that is at least one-block long.
43             *
44             * - When processing the message itself, CTR encryption/decryption is
45             * also done at the same time. The first 'ptr' bytes of buf[] then
46             * contains the encrypted bytes, while the last '16 - ptr' bytes of
47             * buf[] are the remnants of the stream block, to be used against
48             * the next input bytes, when available.
49             *
50             * - The current counter and running CBC-MAC values are kept in 'ctr'
51             * and 'cbcmac', respectively.
52             *
53             * - The derived keys for padding are kept in L2 and L4 (double and
54             * quadruple of Enc_K(0^n), in GF(2^128), respectively).
55             */
56              
57             /*
58             * Start an OMAC computation; the first block is the big-endian
59             * representation of the provided value ('val' must fit on one byte).
60             * We make it a delayed block because it may also be the last one,
61             */
62             static void
63 0           omac_start(br_eax_context *ctx, unsigned val)
64             {
65 0           memset(ctx->cbcmac, 0, sizeof ctx->cbcmac);
66 0           memset(ctx->buf, 0, sizeof ctx->buf);
67 0           ctx->buf[15] = val;
68 0           ctx->ptr = 16;
69 0           }
70              
71             /*
72             * Double a value in finite field GF(2^128), defined with modulus
73             * X^128+X^7+X^2+X+1.
74             */
75             static void
76 0           double_gf128(unsigned char *dst, const unsigned char *src)
77             {
78             unsigned cc;
79             int i;
80              
81 0           cc = 0x87 & -((unsigned)src[0] >> 7);
82 0 0         for (i = 15; i >= 0; i --) {
83             unsigned z;
84              
85 0           z = (src[i] << 1) ^ cc;
86 0           cc = z >> 8;
87 0           dst[i] = (unsigned char)z;
88             }
89 0           }
90              
91             /*
92             * Apply padding to the last block, currently in ctx->buf (with
93             * ctx->ptr bytes), and finalize OMAC computation.
94             */
95             static void
96 0           do_pad(br_eax_context *ctx)
97             {
98             unsigned char *pad;
99             size_t ptr, u;
100              
101 0           ptr = ctx->ptr;
102 0 0         if (ptr == 16) {
103 0           pad = ctx->L2;
104             } else {
105 0           ctx->buf[ptr ++] = 0x80;
106 0           memset(ctx->buf + ptr, 0x00, 16 - ptr);
107 0           pad = ctx->L4;
108             }
109 0 0         for (u = 0; u < sizeof ctx->buf; u ++) {
110 0           ctx->buf[u] ^= pad[u];
111             }
112 0           (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, ctx->buf, sizeof ctx->buf);
113 0           }
114              
115             /*
116             * Apply CBC-MAC on the provided data, with buffering management.
117             *
118             * Upon entry, two situations are acceptable:
119             *
120             * ctx->ptr == 0: there is no data to process in ctx->buf
121             * ctx->ptr == 16: there is a full block of unprocessed data in ctx->buf
122             *
123             * Upon exit, ctx->ptr may be zero only if it was already zero on entry,
124             * and len == 0. In all other situations, ctx->ptr will be non-zero on
125             * exit (and may have value 16).
126             */
127             static void
128 0           do_cbcmac_chunk(br_eax_context *ctx, const void *data, size_t len)
129             {
130             size_t ptr;
131              
132 0 0         if (len == 0) {
133 0           return;
134             }
135 0           ptr = len & (size_t)15;
136 0 0         if (ptr == 0) {
137 0           len -= 16;
138 0           ptr = 16;
139             } else {
140 0           len -= ptr;
141             }
142 0 0         if (ctx->ptr == 16) {
143 0           (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac,
144 0           ctx->buf, sizeof ctx->buf);
145             }
146 0           (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, data, len);
147 0           memcpy(ctx->buf, (const unsigned char *)data + len, ptr);
148 0           ctx->ptr = ptr;
149             }
150              
151             /* see bearssl_aead.h */
152             void
153 0           br_eax_init(br_eax_context *ctx, const br_block_ctrcbc_class **bctx)
154             {
155             unsigned char tmp[16], iv[16];
156              
157 0           ctx->vtable = &br_eax_vtable;
158 0           ctx->bctx = bctx;
159              
160             /*
161             * Encrypt a whole-zero block to compute L2 and L4.
162             */
163 0           memset(tmp, 0, sizeof tmp);
164 0           memset(iv, 0, sizeof iv);
165 0           (*bctx)->ctr(bctx, iv, tmp, sizeof tmp);
166 0           double_gf128(ctx->L2, tmp);
167 0           double_gf128(ctx->L4, ctx->L2);
168 0           }
169              
170             /* see bearssl_aead.h */
171             void
172 0           br_eax_capture(const br_eax_context *ctx, br_eax_state *st)
173             {
174             /*
175             * We capture the three OMAC* states _after_ processing the
176             * initial block (assuming that nonce, message and AAD are
177             * all non-empty).
178             */
179             int i;
180              
181 0           memset(st->st, 0, sizeof st->st);
182 0 0         for (i = 0; i < 3; i ++) {
183             unsigned char tmp[16];
184              
185 0           memset(tmp, 0, sizeof tmp);
186 0           tmp[15] = (unsigned char)i;
187 0           (*ctx->bctx)->mac(ctx->bctx, st->st[i], tmp, sizeof tmp);
188             }
189 0           }
190              
191             /* see bearssl_aead.h */
192             void
193 0           br_eax_reset(br_eax_context *ctx, const void *nonce, size_t len)
194             {
195             /*
196             * Process nonce with OMAC^0.
197             */
198 0           omac_start(ctx, 0);
199 0           do_cbcmac_chunk(ctx, nonce, len);
200 0           do_pad(ctx);
201 0           memcpy(ctx->nonce, ctx->cbcmac, sizeof ctx->cbcmac);
202              
203             /*
204             * Start OMAC^1 for the AAD ("header" in the EAX specification).
205             */
206 0           omac_start(ctx, 1);
207              
208             /*
209             * We use ctx->head[0] as temporary flag to mark that we are
210             * using a "normal" reset().
211             */
212 0           ctx->head[0] = 0;
213 0           }
214              
215             /* see bearssl_aead.h */
216             void
217 0           br_eax_reset_pre_aad(br_eax_context *ctx, const br_eax_state *st,
218             const void *nonce, size_t len)
219             {
220 0 0         if (len == 0) {
221 0           omac_start(ctx, 0);
222             } else {
223 0           memcpy(ctx->cbcmac, st->st[0], sizeof ctx->cbcmac);
224 0           ctx->ptr = 0;
225 0           do_cbcmac_chunk(ctx, nonce, len);
226             }
227 0           do_pad(ctx);
228 0           memcpy(ctx->nonce, ctx->cbcmac, sizeof ctx->cbcmac);
229              
230 0           memcpy(ctx->cbcmac, st->st[1], sizeof ctx->cbcmac);
231 0           ctx->ptr = 0;
232              
233 0           memcpy(ctx->ctr, st->st[2], sizeof ctx->ctr);
234              
235             /*
236             * We use ctx->head[0] as a flag to indicate that we use a
237             * a recorded state, with ctx->ctr containing the preprocessed
238             * first block for OMAC^2.
239             */
240 0           ctx->head[0] = 1;
241 0           }
242              
243             /* see bearssl_aead.h */
244             void
245 0           br_eax_reset_post_aad(br_eax_context *ctx, const br_eax_state *st,
246             const void *nonce, size_t len)
247             {
248 0 0         if (len == 0) {
249 0           omac_start(ctx, 0);
250             } else {
251 0           memcpy(ctx->cbcmac, st->st[0], sizeof ctx->cbcmac);
252 0           ctx->ptr = 0;
253 0           do_cbcmac_chunk(ctx, nonce, len);
254             }
255 0           do_pad(ctx);
256 0           memcpy(ctx->nonce, ctx->cbcmac, sizeof ctx->cbcmac);
257 0           memcpy(ctx->ctr, ctx->nonce, sizeof ctx->nonce);
258              
259 0           memcpy(ctx->head, st->st[1], sizeof ctx->head);
260              
261 0           memcpy(ctx->cbcmac, st->st[2], sizeof ctx->cbcmac);
262 0           ctx->ptr = 0;
263 0           }
264              
265             /* see bearssl_aead.h */
266             void
267 0           br_eax_aad_inject(br_eax_context *ctx, const void *data, size_t len)
268             {
269             size_t ptr;
270              
271 0           ptr = ctx->ptr;
272              
273             /*
274             * If there is a partial block, first complete it.
275             */
276 0 0         if (ptr < 16) {
277             size_t clen;
278              
279 0           clen = 16 - ptr;
280 0 0         if (len <= clen) {
281 0           memcpy(ctx->buf + ptr, data, len);
282 0           ctx->ptr = ptr + len;
283 0           return;
284             }
285 0           memcpy(ctx->buf + ptr, data, clen);
286 0           data = (const unsigned char *)data + clen;
287 0           len -= clen;
288             }
289              
290             /*
291             * We now have a full block in buf[], and this is not the last
292             * block.
293             */
294 0           do_cbcmac_chunk(ctx, data, len);
295             }
296              
297             /* see bearssl_aead.h */
298             void
299 0           br_eax_flip(br_eax_context *ctx)
300             {
301             int from_capture;
302              
303             /*
304             * ctx->head[0] may be non-zero if the context was reset with
305             * a pre-AAD captured state. In that case, ctx->ctr[] contains
306             * the state for OMAC^2 _after_ processing the first block.
307             */
308 0           from_capture = ctx->head[0];
309              
310             /*
311             * Complete the OMAC computation on the AAD.
312             */
313 0           do_pad(ctx);
314 0           memcpy(ctx->head, ctx->cbcmac, sizeof ctx->cbcmac);
315              
316             /*
317             * Start OMAC^2 for the encrypted data.
318             * If the context was initialized from a captured state, then
319             * the OMAC^2 value is in the ctr[] array.
320             */
321 0 0         if (from_capture) {
322 0           memcpy(ctx->cbcmac, ctx->ctr, sizeof ctx->cbcmac);
323 0           ctx->ptr = 0;
324             } else {
325 0           omac_start(ctx, 2);
326             }
327              
328             /*
329             * Initial counter value for CTR is the processed nonce.
330             */
331 0           memcpy(ctx->ctr, ctx->nonce, sizeof ctx->nonce);
332 0           }
333              
334             /* see bearssl_aead.h */
335             void
336 0           br_eax_run(br_eax_context *ctx, int encrypt, void *data, size_t len)
337             {
338             unsigned char *dbuf;
339             size_t ptr;
340              
341             /*
342             * Ensure that there is actual data to process.
343             */
344 0 0         if (len == 0) {
345 0           return;
346             }
347              
348 0           dbuf = data;
349 0           ptr = ctx->ptr;
350              
351             /*
352             * We may have ptr == 0 here if we initialized from a captured
353             * state. In that case, there is no partially consumed block
354             * or unprocessed data.
355             */
356 0 0         if (ptr != 0 && ptr != 16) {
    0          
357             /*
358             * We have a partially consumed block.
359             */
360             size_t u, clen;
361              
362 0           clen = 16 - ptr;
363 0 0         if (len <= clen) {
364 0           clen = len;
365             }
366 0 0         if (encrypt) {
367 0 0         for (u = 0; u < clen; u ++) {
368 0           ctx->buf[ptr + u] ^= dbuf[u];
369             }
370 0           memcpy(dbuf, ctx->buf + ptr, clen);
371             } else {
372 0 0         for (u = 0; u < clen; u ++) {
373             unsigned dx, sx;
374              
375 0           sx = ctx->buf[ptr + u];
376 0           dx = dbuf[u];
377 0           ctx->buf[ptr + u] = dx;
378 0           dbuf[u] = sx ^ dx;
379             }
380             }
381              
382 0 0         if (len <= clen) {
383 0           ctx->ptr = ptr + clen;
384 0           return;
385             }
386 0           dbuf += clen;
387 0           len -= clen;
388             }
389              
390             /*
391             * We now have a complete encrypted block in buf[] that must still
392             * be processed with OMAC, and this is not the final buf.
393             * Exception: when ptr == 0, no block has been produced yet.
394             */
395 0 0         if (ptr != 0) {
396 0           (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac,
397 0           ctx->buf, sizeof ctx->buf);
398             }
399              
400             /*
401             * Do CTR encryption or decryption and CBC-MAC for all full blocks
402             * except the last.
403             */
404 0           ptr = len & (size_t)15;
405 0 0         if (ptr == 0) {
406 0           len -= 16;
407 0           ptr = 16;
408             } else {
409 0           len -= ptr;
410             }
411 0 0         if (encrypt) {
412 0           (*ctx->bctx)->encrypt(ctx->bctx, ctx->ctr, ctx->cbcmac,
413             dbuf, len);
414             } else {
415 0           (*ctx->bctx)->decrypt(ctx->bctx, ctx->ctr, ctx->cbcmac,
416             dbuf, len);
417             }
418 0           dbuf += len;
419              
420             /*
421             * Compute next block of CTR stream, and use it to finish
422             * encrypting or decrypting the data.
423             */
424 0           memset(ctx->buf, 0, sizeof ctx->buf);
425 0           (*ctx->bctx)->ctr(ctx->bctx, ctx->ctr, ctx->buf, sizeof ctx->buf);
426 0 0         if (encrypt) {
427             size_t u;
428              
429 0 0         for (u = 0; u < ptr; u ++) {
430 0           ctx->buf[u] ^= dbuf[u];
431             }
432 0           memcpy(dbuf, ctx->buf, ptr);
433             } else {
434             size_t u;
435              
436 0 0         for (u = 0; u < ptr; u ++) {
437             unsigned dx, sx;
438              
439 0           sx = ctx->buf[u];
440 0           dx = dbuf[u];
441 0           ctx->buf[u] = dx;
442 0           dbuf[u] = sx ^ dx;
443             }
444             }
445 0           ctx->ptr = ptr;
446             }
447              
448             /*
449             * Complete tag computation. The final tag is written in ctx->cbcmac.
450             */
451             static void
452 0           do_final(br_eax_context *ctx)
453             {
454             size_t u;
455              
456 0           do_pad(ctx);
457              
458             /*
459             * Authentication tag is the XOR of the three OMAC outputs for
460             * the nonce, AAD and encrypted data.
461             */
462 0 0         for (u = 0; u < 16; u ++) {
463 0           ctx->cbcmac[u] ^= ctx->nonce[u] ^ ctx->head[u];
464             }
465 0           }
466              
467             /* see bearssl_aead.h */
468             void
469 0           br_eax_get_tag(br_eax_context *ctx, void *tag)
470             {
471 0           do_final(ctx);
472 0           memcpy(tag, ctx->cbcmac, sizeof ctx->cbcmac);
473 0           }
474              
475             /* see bearssl_aead.h */
476             void
477 0           br_eax_get_tag_trunc(br_eax_context *ctx, void *tag, size_t len)
478             {
479 0           do_final(ctx);
480 0           memcpy(tag, ctx->cbcmac, len);
481 0           }
482              
483             /* see bearssl_aead.h */
484             uint32_t
485 0           br_eax_check_tag_trunc(br_eax_context *ctx, const void *tag, size_t len)
486             {
487             unsigned char tmp[16];
488             size_t u;
489             int x;
490              
491 0           br_eax_get_tag(ctx, tmp);
492 0           x = 0;
493 0 0         for (u = 0; u < len; u ++) {
494 0           x |= tmp[u] ^ ((const unsigned char *)tag)[u];
495             }
496 0           return EQ0(x);
497             }
498              
499             /* see bearssl_aead.h */
500             uint32_t
501 0           br_eax_check_tag(br_eax_context *ctx, const void *tag)
502             {
503 0           return br_eax_check_tag_trunc(ctx, tag, 16);
504             }
505              
506             /* see bearssl_aead.h */
507             const br_aead_class br_eax_vtable = {
508             16,
509             (void (*)(const br_aead_class **, const void *, size_t))
510             &br_eax_reset,
511             (void (*)(const br_aead_class **, const void *, size_t))
512             &br_eax_aad_inject,
513             (void (*)(const br_aead_class **))
514             &br_eax_flip,
515             (void (*)(const br_aead_class **, int, void *, size_t))
516             &br_eax_run,
517             (void (*)(const br_aead_class **, void *))
518             &br_eax_get_tag,
519             (uint32_t (*)(const br_aead_class **, const void *))
520             &br_eax_check_tag,
521             (void (*)(const br_aead_class **, void *, size_t))
522             &br_eax_get_tag_trunc,
523             (uint32_t (*)(const br_aead_class **, const void *, size_t))
524             &br_eax_check_tag_trunc
525             };