Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/bearssl/src/aead/eax.c
39488 views
1
/*
2
* Copyright (c) 2017 Thomas Pornin <[email protected]>
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
omac_start(br_eax_context *ctx, unsigned val)
64
{
65
memset(ctx->cbcmac, 0, sizeof ctx->cbcmac);
66
memset(ctx->buf, 0, sizeof ctx->buf);
67
ctx->buf[15] = val;
68
ctx->ptr = 16;
69
}
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
double_gf128(unsigned char *dst, const unsigned char *src)
77
{
78
unsigned cc;
79
int i;
80
81
cc = 0x87 & -((unsigned)src[0] >> 7);
82
for (i = 15; i >= 0; i --) {
83
unsigned z;
84
85
z = (src[i] << 1) ^ cc;
86
cc = z >> 8;
87
dst[i] = (unsigned char)z;
88
}
89
}
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
do_pad(br_eax_context *ctx)
97
{
98
unsigned char *pad;
99
size_t ptr, u;
100
101
ptr = ctx->ptr;
102
if (ptr == 16) {
103
pad = ctx->L2;
104
} else {
105
ctx->buf[ptr ++] = 0x80;
106
memset(ctx->buf + ptr, 0x00, 16 - ptr);
107
pad = ctx->L4;
108
}
109
for (u = 0; u < sizeof ctx->buf; u ++) {
110
ctx->buf[u] ^= pad[u];
111
}
112
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, ctx->buf, sizeof ctx->buf);
113
}
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
do_cbcmac_chunk(br_eax_context *ctx, const void *data, size_t len)
129
{
130
size_t ptr;
131
132
if (len == 0) {
133
return;
134
}
135
ptr = len & (size_t)15;
136
if (ptr == 0) {
137
len -= 16;
138
ptr = 16;
139
} else {
140
len -= ptr;
141
}
142
if (ctx->ptr == 16) {
143
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac,
144
ctx->buf, sizeof ctx->buf);
145
}
146
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, data, len);
147
memcpy(ctx->buf, (const unsigned char *)data + len, ptr);
148
ctx->ptr = ptr;
149
}
150
151
/* see bearssl_aead.h */
152
void
153
br_eax_init(br_eax_context *ctx, const br_block_ctrcbc_class **bctx)
154
{
155
unsigned char tmp[16], iv[16];
156
157
ctx->vtable = &br_eax_vtable;
158
ctx->bctx = bctx;
159
160
/*
161
* Encrypt a whole-zero block to compute L2 and L4.
162
*/
163
memset(tmp, 0, sizeof tmp);
164
memset(iv, 0, sizeof iv);
165
(*bctx)->ctr(bctx, iv, tmp, sizeof tmp);
166
double_gf128(ctx->L2, tmp);
167
double_gf128(ctx->L4, ctx->L2);
168
}
169
170
/* see bearssl_aead.h */
171
void
172
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
memset(st->st, 0, sizeof st->st);
182
for (i = 0; i < 3; i ++) {
183
unsigned char tmp[16];
184
185
memset(tmp, 0, sizeof tmp);
186
tmp[15] = (unsigned char)i;
187
(*ctx->bctx)->mac(ctx->bctx, st->st[i], tmp, sizeof tmp);
188
}
189
}
190
191
/* see bearssl_aead.h */
192
void
193
br_eax_reset(br_eax_context *ctx, const void *nonce, size_t len)
194
{
195
/*
196
* Process nonce with OMAC^0.
197
*/
198
omac_start(ctx, 0);
199
do_cbcmac_chunk(ctx, nonce, len);
200
do_pad(ctx);
201
memcpy(ctx->nonce, ctx->cbcmac, sizeof ctx->cbcmac);
202
203
/*
204
* Start OMAC^1 for the AAD ("header" in the EAX specification).
205
*/
206
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
ctx->head[0] = 0;
213
}
214
215
/* see bearssl_aead.h */
216
void
217
br_eax_reset_pre_aad(br_eax_context *ctx, const br_eax_state *st,
218
const void *nonce, size_t len)
219
{
220
if (len == 0) {
221
omac_start(ctx, 0);
222
} else {
223
memcpy(ctx->cbcmac, st->st[0], sizeof ctx->cbcmac);
224
ctx->ptr = 0;
225
do_cbcmac_chunk(ctx, nonce, len);
226
}
227
do_pad(ctx);
228
memcpy(ctx->nonce, ctx->cbcmac, sizeof ctx->cbcmac);
229
230
memcpy(ctx->cbcmac, st->st[1], sizeof ctx->cbcmac);
231
ctx->ptr = 0;
232
233
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
ctx->head[0] = 1;
241
}
242
243
/* see bearssl_aead.h */
244
void
245
br_eax_reset_post_aad(br_eax_context *ctx, const br_eax_state *st,
246
const void *nonce, size_t len)
247
{
248
if (len == 0) {
249
omac_start(ctx, 0);
250
} else {
251
memcpy(ctx->cbcmac, st->st[0], sizeof ctx->cbcmac);
252
ctx->ptr = 0;
253
do_cbcmac_chunk(ctx, nonce, len);
254
}
255
do_pad(ctx);
256
memcpy(ctx->nonce, ctx->cbcmac, sizeof ctx->cbcmac);
257
memcpy(ctx->ctr, ctx->nonce, sizeof ctx->nonce);
258
259
memcpy(ctx->head, st->st[1], sizeof ctx->head);
260
261
memcpy(ctx->cbcmac, st->st[2], sizeof ctx->cbcmac);
262
ctx->ptr = 0;
263
}
264
265
/* see bearssl_aead.h */
266
void
267
br_eax_aad_inject(br_eax_context *ctx, const void *data, size_t len)
268
{
269
size_t ptr;
270
271
ptr = ctx->ptr;
272
273
/*
274
* If there is a partial block, first complete it.
275
*/
276
if (ptr < 16) {
277
size_t clen;
278
279
clen = 16 - ptr;
280
if (len <= clen) {
281
memcpy(ctx->buf + ptr, data, len);
282
ctx->ptr = ptr + len;
283
return;
284
}
285
memcpy(ctx->buf + ptr, data, clen);
286
data = (const unsigned char *)data + clen;
287
len -= clen;
288
}
289
290
/*
291
* We now have a full block in buf[], and this is not the last
292
* block.
293
*/
294
do_cbcmac_chunk(ctx, data, len);
295
}
296
297
/* see bearssl_aead.h */
298
void
299
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
from_capture = ctx->head[0];
309
310
/*
311
* Complete the OMAC computation on the AAD.
312
*/
313
do_pad(ctx);
314
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
if (from_capture) {
322
memcpy(ctx->cbcmac, ctx->ctr, sizeof ctx->cbcmac);
323
ctx->ptr = 0;
324
} else {
325
omac_start(ctx, 2);
326
}
327
328
/*
329
* Initial counter value for CTR is the processed nonce.
330
*/
331
memcpy(ctx->ctr, ctx->nonce, sizeof ctx->nonce);
332
}
333
334
/* see bearssl_aead.h */
335
void
336
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
if (len == 0) {
345
return;
346
}
347
348
dbuf = data;
349
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
if (ptr != 0 && ptr != 16) {
357
/*
358
* We have a partially consumed block.
359
*/
360
size_t u, clen;
361
362
clen = 16 - ptr;
363
if (len <= clen) {
364
clen = len;
365
}
366
if (encrypt) {
367
for (u = 0; u < clen; u ++) {
368
ctx->buf[ptr + u] ^= dbuf[u];
369
}
370
memcpy(dbuf, ctx->buf + ptr, clen);
371
} else {
372
for (u = 0; u < clen; u ++) {
373
unsigned dx, sx;
374
375
sx = ctx->buf[ptr + u];
376
dx = dbuf[u];
377
ctx->buf[ptr + u] = dx;
378
dbuf[u] = sx ^ dx;
379
}
380
}
381
382
if (len <= clen) {
383
ctx->ptr = ptr + clen;
384
return;
385
}
386
dbuf += clen;
387
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
if (ptr != 0) {
396
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac,
397
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
ptr = len & (size_t)15;
405
if (ptr == 0) {
406
len -= 16;
407
ptr = 16;
408
} else {
409
len -= ptr;
410
}
411
if (encrypt) {
412
(*ctx->bctx)->encrypt(ctx->bctx, ctx->ctr, ctx->cbcmac,
413
dbuf, len);
414
} else {
415
(*ctx->bctx)->decrypt(ctx->bctx, ctx->ctr, ctx->cbcmac,
416
dbuf, len);
417
}
418
dbuf += len;
419
420
/*
421
* Compute next block of CTR stream, and use it to finish
422
* encrypting or decrypting the data.
423
*/
424
memset(ctx->buf, 0, sizeof ctx->buf);
425
(*ctx->bctx)->ctr(ctx->bctx, ctx->ctr, ctx->buf, sizeof ctx->buf);
426
if (encrypt) {
427
size_t u;
428
429
for (u = 0; u < ptr; u ++) {
430
ctx->buf[u] ^= dbuf[u];
431
}
432
memcpy(dbuf, ctx->buf, ptr);
433
} else {
434
size_t u;
435
436
for (u = 0; u < ptr; u ++) {
437
unsigned dx, sx;
438
439
sx = ctx->buf[u];
440
dx = dbuf[u];
441
ctx->buf[u] = dx;
442
dbuf[u] = sx ^ dx;
443
}
444
}
445
ctx->ptr = ptr;
446
}
447
448
/*
449
* Complete tag computation. The final tag is written in ctx->cbcmac.
450
*/
451
static void
452
do_final(br_eax_context *ctx)
453
{
454
size_t u;
455
456
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
for (u = 0; u < 16; u ++) {
463
ctx->cbcmac[u] ^= ctx->nonce[u] ^ ctx->head[u];
464
}
465
}
466
467
/* see bearssl_aead.h */
468
void
469
br_eax_get_tag(br_eax_context *ctx, void *tag)
470
{
471
do_final(ctx);
472
memcpy(tag, ctx->cbcmac, sizeof ctx->cbcmac);
473
}
474
475
/* see bearssl_aead.h */
476
void
477
br_eax_get_tag_trunc(br_eax_context *ctx, void *tag, size_t len)
478
{
479
do_final(ctx);
480
memcpy(tag, ctx->cbcmac, len);
481
}
482
483
/* see bearssl_aead.h */
484
uint32_t
485
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
br_eax_get_tag(ctx, tmp);
492
x = 0;
493
for (u = 0; u < len; u ++) {
494
x |= tmp[u] ^ ((const unsigned char *)tag)[u];
495
}
496
return EQ0(x);
497
}
498
499
/* see bearssl_aead.h */
500
uint32_t
501
br_eax_check_tag(br_eax_context *ctx, const void *tag)
502
{
503
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
};
526
527