Coverage Report

Created: 2022-11-30 06:20

/src/openssl/crypto/modes/ccm128.c
Line
Count
Source (jump to first uncovered line)
1
/* ====================================================================
2
 * Copyright (c) 2011 The OpenSSL Project.  All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 *
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in
13
 *    the documentation and/or other materials provided with the
14
 *    distribution.
15
 *
16
 * 3. All advertising materials mentioning features or use of this
17
 *    software must display the following acknowledgment:
18
 *    "This product includes software developed by the OpenSSL Project
19
 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
20
 *
21
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22
 *    endorse or promote products derived from this software without
23
 *    prior written permission. For written permission, please contact
24
 *    openssl-core@openssl.org.
25
 *
26
 * 5. Products derived from this software may not be called "OpenSSL"
27
 *    nor may "OpenSSL" appear in their names without prior written
28
 *    permission of the OpenSSL Project.
29
 *
30
 * 6. Redistributions of any form whatsoever must retain the following
31
 *    acknowledgment:
32
 *    "This product includes software developed by the OpenSSL Project
33
 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
34
 *
35
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
36
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
39
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46
 * OF THE POSSIBILITY OF SUCH DAMAGE.
47
 * ====================================================================
48
 */
49
50
#include <openssl/crypto.h>
51
#include "modes_lcl.h"
52
#include <string.h>
53
54
#ifndef MODES_DEBUG
55
# ifndef NDEBUG
56
#  define NDEBUG
57
# endif
58
#endif
59
#include <assert.h>
60
61
/*
62
 * First you setup M and L parameters and pass the key schedule. This is
63
 * called once per session setup...
64
 */
65
void CRYPTO_ccm128_init(CCM128_CONTEXT *ctx,
66
                        unsigned int M, unsigned int L, void *key,
67
                        block128_f block)
68
0
{
69
0
    memset(ctx->nonce.c, 0, sizeof(ctx->nonce.c));
70
0
    ctx->nonce.c[0] = ((u8)(L - 1) & 7) | (u8)(((M - 2) / 2) & 7) << 3;
71
0
    ctx->blocks = 0;
72
0
    ctx->block = block;
73
0
    ctx->key = key;
74
0
}
75
76
/* !!! Following interfaces are to be called *once* per packet !!! */
77
78
/* Then you setup per-message nonce and pass the length of the message */
79
int CRYPTO_ccm128_setiv(CCM128_CONTEXT *ctx,
80
                        const unsigned char *nonce, size_t nlen, size_t mlen)
81
0
{
82
0
    unsigned int L = ctx->nonce.c[0] & 7; /* the L parameter */
83
84
0
    if (nlen < (14 - L))
85
0
        return -1;              /* nonce is too short */
86
87
0
    if (sizeof(mlen) == 8 && L >= 3) {
88
0
        ctx->nonce.c[8] = (u8)(mlen >> (56 % (sizeof(mlen) * 8)));
89
0
        ctx->nonce.c[9] = (u8)(mlen >> (48 % (sizeof(mlen) * 8)));
90
0
        ctx->nonce.c[10] = (u8)(mlen >> (40 % (sizeof(mlen) * 8)));
91
0
        ctx->nonce.c[11] = (u8)(mlen >> (32 % (sizeof(mlen) * 8)));
92
0
    } else
93
0
        ctx->nonce.u[1] = 0;
94
95
0
    ctx->nonce.c[12] = (u8)(mlen >> 24);
96
0
    ctx->nonce.c[13] = (u8)(mlen >> 16);
97
0
    ctx->nonce.c[14] = (u8)(mlen >> 8);
98
0
    ctx->nonce.c[15] = (u8)mlen;
99
100
0
    ctx->nonce.c[0] &= ~0x40;   /* clear Adata flag */
101
0
    memcpy(&ctx->nonce.c[1], nonce, 14 - L);
102
103
0
    return 0;
104
0
}
105
106
/* Then you pass additional authentication data, this is optional */
107
void CRYPTO_ccm128_aad(CCM128_CONTEXT *ctx,
108
                       const unsigned char *aad, size_t alen)
109
0
{
110
0
    unsigned int i;
111
0
    block128_f block = ctx->block;
112
113
0
    if (alen == 0)
114
0
        return;
115
116
0
    ctx->nonce.c[0] |= 0x40;    /* set Adata flag */
117
0
    (*block) (ctx->nonce.c, ctx->cmac.c, ctx->key), ctx->blocks++;
118
119
0
    if (alen < (0x10000 - 0x100)) {
120
0
        ctx->cmac.c[0] ^= (u8)(alen >> 8);
121
0
        ctx->cmac.c[1] ^= (u8)alen;
122
0
        i = 2;
123
0
    } else if (sizeof(alen) == 8
124
0
               && alen >= (size_t)1 << (32 % (sizeof(alen) * 8))) {
125
0
        ctx->cmac.c[0] ^= 0xFF;
126
0
        ctx->cmac.c[1] ^= 0xFF;
127
0
        ctx->cmac.c[2] ^= (u8)(alen >> (56 % (sizeof(alen) * 8)));
128
0
        ctx->cmac.c[3] ^= (u8)(alen >> (48 % (sizeof(alen) * 8)));
129
0
        ctx->cmac.c[4] ^= (u8)(alen >> (40 % (sizeof(alen) * 8)));
130
0
        ctx->cmac.c[5] ^= (u8)(alen >> (32 % (sizeof(alen) * 8)));
131
0
        ctx->cmac.c[6] ^= (u8)(alen >> 24);
132
0
        ctx->cmac.c[7] ^= (u8)(alen >> 16);
133
0
        ctx->cmac.c[8] ^= (u8)(alen >> 8);
134
0
        ctx->cmac.c[9] ^= (u8)alen;
135
0
        i = 10;
136
0
    } else {
137
0
        ctx->cmac.c[0] ^= 0xFF;
138
0
        ctx->cmac.c[1] ^= 0xFE;
139
0
        ctx->cmac.c[2] ^= (u8)(alen >> 24);
140
0
        ctx->cmac.c[3] ^= (u8)(alen >> 16);
141
0
        ctx->cmac.c[4] ^= (u8)(alen >> 8);
142
0
        ctx->cmac.c[5] ^= (u8)alen;
143
0
        i = 6;
144
0
    }
145
146
0
    do {
147
0
        for (; i < 16 && alen; ++i, ++aad, --alen)
148
0
            ctx->cmac.c[i] ^= *aad;
149
0
        (*block) (ctx->cmac.c, ctx->cmac.c, ctx->key), ctx->blocks++;
150
0
        i = 0;
151
0
    } while (alen);
152
0
}
153
154
/* Finally you encrypt or decrypt the message */
155
156
/*
157
 * counter part of nonce may not be larger than L*8 bits, L is not larger
158
 * than 8, therefore 64-bit counter...
159
 */
160
static void ctr64_inc(unsigned char *counter)
161
0
{
162
0
    unsigned int n = 8;
163
0
    u8 c;
164
165
0
    counter += 8;
166
0
    do {
167
0
        --n;
168
0
        c = counter[n];
169
0
        ++c;
170
0
        counter[n] = c;
171
0
        if (c)
172
0
            return;
173
0
    } while (n);
174
0
}
175
176
int CRYPTO_ccm128_encrypt(CCM128_CONTEXT *ctx,
177
                          const unsigned char *inp, unsigned char *out,
178
                          size_t len)
179
0
{
180
0
    size_t n;
181
0
    unsigned int i, L;
182
0
    unsigned char flags0 = ctx->nonce.c[0];
183
0
    block128_f block = ctx->block;
184
0
    void *key = ctx->key;
185
0
    union {
186
0
        u64 u[2];
187
0
        u8 c[16];
188
0
    } scratch;
189
190
0
    if (!(flags0 & 0x40))
191
0
        (*block) (ctx->nonce.c, ctx->cmac.c, key), ctx->blocks++;
192
193
0
    ctx->nonce.c[0] = L = flags0 & 7;
194
0
    for (n = 0, i = 15 - L; i < 15; ++i) {
195
0
        n |= ctx->nonce.c[i];
196
0
        ctx->nonce.c[i] = 0;
197
0
        n <<= 8;
198
0
    }
199
0
    n |= ctx->nonce.c[15];      /* reconstructed length */
200
0
    ctx->nonce.c[15] = 1;
201
202
0
    if (n != len)
203
0
        return -1;              /* length mismatch */
204
205
0
    ctx->blocks += ((len + 15) >> 3) | 1;
206
0
    if (ctx->blocks > (U64(1) << 61))
207
0
        return -2;              /* too much data */
208
209
0
    while (len >= 16) {
210
0
#if defined(STRICT_ALIGNMENT)
211
0
        union {
212
0
            u64 u[2];
213
0
            u8 c[16];
214
0
        } temp;
215
216
0
        memcpy(temp.c, inp, 16);
217
0
        ctx->cmac.u[0] ^= temp.u[0];
218
0
        ctx->cmac.u[1] ^= temp.u[1];
219
#else
220
        ctx->cmac.u[0] ^= ((u64 *)inp)[0];
221
        ctx->cmac.u[1] ^= ((u64 *)inp)[1];
222
#endif
223
0
        (*block) (ctx->cmac.c, ctx->cmac.c, key);
224
0
        (*block) (ctx->nonce.c, scratch.c, key);
225
0
        ctr64_inc(ctx->nonce.c);
226
0
#if defined(STRICT_ALIGNMENT)
227
0
        temp.u[0] ^= scratch.u[0];
228
0
        temp.u[1] ^= scratch.u[1];
229
0
        memcpy(out, temp.c, 16);
230
#else
231
        ((u64 *)out)[0] = scratch.u[0] ^ ((u64 *)inp)[0];
232
        ((u64 *)out)[1] = scratch.u[1] ^ ((u64 *)inp)[1];
233
#endif
234
0
        inp += 16;
235
0
        out += 16;
236
0
        len -= 16;
237
0
    }
238
239
0
    if (len) {
240
0
        for (i = 0; i < len; ++i)
241
0
            ctx->cmac.c[i] ^= inp[i];
242
0
        (*block) (ctx->cmac.c, ctx->cmac.c, key);
243
0
        (*block) (ctx->nonce.c, scratch.c, key);
244
0
        for (i = 0; i < len; ++i)
245
0
            out[i] = scratch.c[i] ^ inp[i];
246
0
    }
247
248
0
    for (i = 15 - L; i < 16; ++i)
249
0
        ctx->nonce.c[i] = 0;
250
251
0
    (*block) (ctx->nonce.c, scratch.c, key);
252
0
    ctx->cmac.u[0] ^= scratch.u[0];
253
0
    ctx->cmac.u[1] ^= scratch.u[1];
254
255
0
    ctx->nonce.c[0] = flags0;
256
257
0
    return 0;
258
0
}
259
260
int CRYPTO_ccm128_decrypt(CCM128_CONTEXT *ctx,
261
                          const unsigned char *inp, unsigned char *out,
262
                          size_t len)
263
0
{
264
0
    size_t n;
265
0
    unsigned int i, L;
266
0
    unsigned char flags0 = ctx->nonce.c[0];
267
0
    block128_f block = ctx->block;
268
0
    void *key = ctx->key;
269
0
    union {
270
0
        u64 u[2];
271
0
        u8 c[16];
272
0
    } scratch;
273
274
0
    if (!(flags0 & 0x40))
275
0
        (*block) (ctx->nonce.c, ctx->cmac.c, key);
276
277
0
    ctx->nonce.c[0] = L = flags0 & 7;
278
0
    for (n = 0, i = 15 - L; i < 15; ++i) {
279
0
        n |= ctx->nonce.c[i];
280
0
        ctx->nonce.c[i] = 0;
281
0
        n <<= 8;
282
0
    }
283
0
    n |= ctx->nonce.c[15];      /* reconstructed length */
284
0
    ctx->nonce.c[15] = 1;
285
286
0
    if (n != len)
287
0
        return -1;
288
289
0
    while (len >= 16) {
290
0
#if defined(STRICT_ALIGNMENT)
291
0
        union {
292
0
            u64 u[2];
293
0
            u8 c[16];
294
0
        } temp;
295
0
#endif
296
0
        (*block) (ctx->nonce.c, scratch.c, key);
297
0
        ctr64_inc(ctx->nonce.c);
298
0
#if defined(STRICT_ALIGNMENT)
299
0
        memcpy(temp.c, inp, 16);
300
0
        ctx->cmac.u[0] ^= (scratch.u[0] ^= temp.u[0]);
301
0
        ctx->cmac.u[1] ^= (scratch.u[1] ^= temp.u[1]);
302
0
        memcpy(out, scratch.c, 16);
303
#else
304
        ctx->cmac.u[0] ^= (((u64 *)out)[0] = scratch.u[0] ^ ((u64 *)inp)[0]);
305
        ctx->cmac.u[1] ^= (((u64 *)out)[1] = scratch.u[1] ^ ((u64 *)inp)[1]);
306
#endif
307
0
        (*block) (ctx->cmac.c, ctx->cmac.c, key);
308
309
0
        inp += 16;
310
0
        out += 16;
311
0
        len -= 16;
312
0
    }
313
314
0
    if (len) {
315
0
        (*block) (ctx->nonce.c, scratch.c, key);
316
0
        for (i = 0; i < len; ++i)
317
0
            ctx->cmac.c[i] ^= (out[i] = scratch.c[i] ^ inp[i]);
318
0
        (*block) (ctx->cmac.c, ctx->cmac.c, key);
319
0
    }
320
321
0
    for (i = 15 - L; i < 16; ++i)
322
0
        ctx->nonce.c[i] = 0;
323
324
0
    (*block) (ctx->nonce.c, scratch.c, key);
325
0
    ctx->cmac.u[0] ^= scratch.u[0];
326
0
    ctx->cmac.u[1] ^= scratch.u[1];
327
328
0
    ctx->nonce.c[0] = flags0;
329
330
0
    return 0;
331
0
}
332
333
static void ctr64_add(unsigned char *counter, size_t inc)
334
0
{
335
0
    size_t n = 8, val = 0;
336
337
0
    counter += 8;
338
0
    do {
339
0
        --n;
340
0
        val += counter[n] + (inc & 0xff);
341
0
        counter[n] = (unsigned char)val;
342
0
        val >>= 8;              /* carry bit */
343
0
        inc >>= 8;
344
0
    } while (n && (inc || val));
345
0
}
346
347
int CRYPTO_ccm128_encrypt_ccm64(CCM128_CONTEXT *ctx,
348
                                const unsigned char *inp, unsigned char *out,
349
                                size_t len, ccm128_f stream)
350
0
{
351
0
    size_t n;
352
0
    unsigned int i, L;
353
0
    unsigned char flags0 = ctx->nonce.c[0];
354
0
    block128_f block = ctx->block;
355
0
    void *key = ctx->key;
356
0
    union {
357
0
        u64 u[2];
358
0
        u8 c[16];
359
0
    } scratch;
360
361
0
    if (!(flags0 & 0x40))
362
0
        (*block) (ctx->nonce.c, ctx->cmac.c, key), ctx->blocks++;
363
364
0
    ctx->nonce.c[0] = L = flags0 & 7;
365
0
    for (n = 0, i = 15 - L; i < 15; ++i) {
366
0
        n |= ctx->nonce.c[i];
367
0
        ctx->nonce.c[i] = 0;
368
0
        n <<= 8;
369
0
    }
370
0
    n |= ctx->nonce.c[15];      /* reconstructed length */
371
0
    ctx->nonce.c[15] = 1;
372
373
0
    if (n != len)
374
0
        return -1;              /* length mismatch */
375
376
0
    ctx->blocks += ((len + 15) >> 3) | 1;
377
0
    if (ctx->blocks > (U64(1) << 61))
378
0
        return -2;              /* too much data */
379
380
0
    if ((n = len / 16)) {
381
0
        (*stream) (inp, out, n, key, ctx->nonce.c, ctx->cmac.c);
382
0
        n *= 16;
383
0
        inp += n;
384
0
        out += n;
385
0
        len -= n;
386
0
        if (len)
387
0
            ctr64_add(ctx->nonce.c, n / 16);
388
0
    }
389
390
0
    if (len) {
391
0
        for (i = 0; i < len; ++i)
392
0
            ctx->cmac.c[i] ^= inp[i];
393
0
        (*block) (ctx->cmac.c, ctx->cmac.c, key);
394
0
        (*block) (ctx->nonce.c, scratch.c, key);
395
0
        for (i = 0; i < len; ++i)
396
0
            out[i] = scratch.c[i] ^ inp[i];
397
0
    }
398
399
0
    for (i = 15 - L; i < 16; ++i)
400
0
        ctx->nonce.c[i] = 0;
401
402
0
    (*block) (ctx->nonce.c, scratch.c, key);
403
0
    ctx->cmac.u[0] ^= scratch.u[0];
404
0
    ctx->cmac.u[1] ^= scratch.u[1];
405
406
0
    ctx->nonce.c[0] = flags0;
407
408
0
    return 0;
409
0
}
410
411
int CRYPTO_ccm128_decrypt_ccm64(CCM128_CONTEXT *ctx,
412
                                const unsigned char *inp, unsigned char *out,
413
                                size_t len, ccm128_f stream)
414
0
{
415
0
    size_t n;
416
0
    unsigned int i, L;
417
0
    unsigned char flags0 = ctx->nonce.c[0];
418
0
    block128_f block = ctx->block;
419
0
    void *key = ctx->key;
420
0
    union {
421
0
        u64 u[2];
422
0
        u8 c[16];
423
0
    } scratch;
424
425
0
    if (!(flags0 & 0x40))
426
0
        (*block) (ctx->nonce.c, ctx->cmac.c, key);
427
428
0
    ctx->nonce.c[0] = L = flags0 & 7;
429
0
    for (n = 0, i = 15 - L; i < 15; ++i) {
430
0
        n |= ctx->nonce.c[i];
431
0
        ctx->nonce.c[i] = 0;
432
0
        n <<= 8;
433
0
    }
434
0
    n |= ctx->nonce.c[15];      /* reconstructed length */
435
0
    ctx->nonce.c[15] = 1;
436
437
0
    if (n != len)
438
0
        return -1;
439
440
0
    if ((n = len / 16)) {
441
0
        (*stream) (inp, out, n, key, ctx->nonce.c, ctx->cmac.c);
442
0
        n *= 16;
443
0
        inp += n;
444
0
        out += n;
445
0
        len -= n;
446
0
        if (len)
447
0
            ctr64_add(ctx->nonce.c, n / 16);
448
0
    }
449
450
0
    if (len) {
451
0
        (*block) (ctx->nonce.c, scratch.c, key);
452
0
        for (i = 0; i < len; ++i)
453
0
            ctx->cmac.c[i] ^= (out[i] = scratch.c[i] ^ inp[i]);
454
0
        (*block) (ctx->cmac.c, ctx->cmac.c, key);
455
0
    }
456
457
0
    for (i = 15 - L; i < 16; ++i)
458
0
        ctx->nonce.c[i] = 0;
459
460
0
    (*block) (ctx->nonce.c, scratch.c, key);
461
0
    ctx->cmac.u[0] ^= scratch.u[0];
462
0
    ctx->cmac.u[1] ^= scratch.u[1];
463
464
0
    ctx->nonce.c[0] = flags0;
465
466
0
    return 0;
467
0
}
468
469
size_t CRYPTO_ccm128_tag(CCM128_CONTEXT *ctx, unsigned char *tag, size_t len)
470
0
{
471
0
    unsigned int M = (ctx->nonce.c[0] >> 3) & 7; /* the M parameter */
472
473
0
    M *= 2;
474
0
    M += 2;
475
0
    if (len < M)
476
0
        return 0;
477
0
    memcpy(tag, ctx->cmac.c, M);
478
0
    return M;
479
0
}