Coverage Report

Created: 2025-08-11 07:04

/src/openssl32/crypto/modes/ccm128.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License 2.0 (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
#include <string.h>
11
#include <openssl/crypto.h>
12
#include "crypto/modes.h"
13
14
#ifndef STRICT_ALIGNMENT
15
# ifdef __GNUC__
16
typedef u64 u64_a1 __attribute((__aligned__(1)));
17
# else
18
typedef u64 u64_a1;
19
# endif
20
#endif
21
22
/*
23
 * First you setup M and L parameters and pass the key schedule. This is
24
 * called once per session setup...
25
 */
26
void CRYPTO_ccm128_init(CCM128_CONTEXT *ctx,
27
                        unsigned int M, unsigned int L, void *key,
28
                        block128_f block)
29
1.23k
{
30
1.23k
    memset(ctx->nonce.c, 0, sizeof(ctx->nonce.c));
31
1.23k
    ctx->nonce.c[0] = ((u8)(L - 1) & 7) | (u8)(((M - 2) / 2) & 7) << 3;
32
1.23k
    ctx->blocks = 0;
33
1.23k
    ctx->block = block;
34
1.23k
    ctx->key = key;
35
1.23k
}
36
37
/* !!! Following interfaces are to be called *once* per packet !!! */
38
39
/* Then you setup per-message nonce and pass the length of the message */
40
int CRYPTO_ccm128_setiv(CCM128_CONTEXT *ctx,
41
                        const unsigned char *nonce, size_t nlen, size_t mlen)
42
38.2k
{
43
38.2k
    unsigned int L = ctx->nonce.c[0] & 7; /* the L parameter */
44
45
38.2k
    if (nlen < (14 - L))
46
0
        return -1;              /* nonce is too short */
47
48
38.2k
    if (sizeof(mlen) == 8 && L >= 3) {
49
0
        ctx->nonce.c[8] = (u8)(mlen >> (56 % (sizeof(mlen) * 8)));
50
0
        ctx->nonce.c[9] = (u8)(mlen >> (48 % (sizeof(mlen) * 8)));
51
0
        ctx->nonce.c[10] = (u8)(mlen >> (40 % (sizeof(mlen) * 8)));
52
0
        ctx->nonce.c[11] = (u8)(mlen >> (32 % (sizeof(mlen) * 8)));
53
0
    } else
54
38.2k
        ctx->nonce.u[1] = 0;
55
56
38.2k
    ctx->nonce.c[12] = (u8)(mlen >> 24);
57
38.2k
    ctx->nonce.c[13] = (u8)(mlen >> 16);
58
38.2k
    ctx->nonce.c[14] = (u8)(mlen >> 8);
59
38.2k
    ctx->nonce.c[15] = (u8)mlen;
60
61
38.2k
    ctx->nonce.c[0] &= ~0x40;   /* clear Adata flag */
62
38.2k
    memcpy(&ctx->nonce.c[1], nonce, 14 - L);
63
64
38.2k
    return 0;
65
38.2k
}
66
67
/* Then you pass additional authentication data, this is optional */
68
void CRYPTO_ccm128_aad(CCM128_CONTEXT *ctx,
69
                       const unsigned char *aad, size_t alen)
70
38.2k
{
71
38.2k
    unsigned int i;
72
38.2k
    block128_f block = ctx->block;
73
74
38.2k
    if (alen == 0)
75
0
        return;
76
77
38.2k
    ctx->nonce.c[0] |= 0x40;    /* set Adata flag */
78
38.2k
    (*block) (ctx->nonce.c, ctx->cmac.c, ctx->key), ctx->blocks++;
79
80
38.2k
    if (alen < (0x10000 - 0x100)) {
81
38.2k
        ctx->cmac.c[0] ^= (u8)(alen >> 8);
82
38.2k
        ctx->cmac.c[1] ^= (u8)alen;
83
38.2k
        i = 2;
84
38.2k
    } else if (sizeof(alen) == 8
85
0
               && alen >= (size_t)1 << (32 % (sizeof(alen) * 8))) {
86
0
        ctx->cmac.c[0] ^= 0xFF;
87
0
        ctx->cmac.c[1] ^= 0xFF;
88
0
        ctx->cmac.c[2] ^= (u8)(alen >> (56 % (sizeof(alen) * 8)));
89
0
        ctx->cmac.c[3] ^= (u8)(alen >> (48 % (sizeof(alen) * 8)));
90
0
        ctx->cmac.c[4] ^= (u8)(alen >> (40 % (sizeof(alen) * 8)));
91
0
        ctx->cmac.c[5] ^= (u8)(alen >> (32 % (sizeof(alen) * 8)));
92
0
        ctx->cmac.c[6] ^= (u8)(alen >> 24);
93
0
        ctx->cmac.c[7] ^= (u8)(alen >> 16);
94
0
        ctx->cmac.c[8] ^= (u8)(alen >> 8);
95
0
        ctx->cmac.c[9] ^= (u8)alen;
96
0
        i = 10;
97
0
    } else {
98
0
        ctx->cmac.c[0] ^= 0xFF;
99
0
        ctx->cmac.c[1] ^= 0xFE;
100
0
        ctx->cmac.c[2] ^= (u8)(alen >> 24);
101
0
        ctx->cmac.c[3] ^= (u8)(alen >> 16);
102
0
        ctx->cmac.c[4] ^= (u8)(alen >> 8);
103
0
        ctx->cmac.c[5] ^= (u8)alen;
104
0
        i = 6;
105
0
    }
106
107
38.2k
    do {
108
536k
        for (; i < 16 && alen; ++i, ++aad, --alen)
109
497k
            ctx->cmac.c[i] ^= *aad;
110
38.2k
        (*block) (ctx->cmac.c, ctx->cmac.c, ctx->key), ctx->blocks++;
111
38.2k
        i = 0;
112
38.2k
    } while (alen);
113
38.2k
}
114
115
/* Finally you encrypt or decrypt the message */
116
117
/*
118
 * counter part of nonce may not be larger than L*8 bits, L is not larger
119
 * than 8, therefore 64-bit counter...
120
 */
121
static void ctr64_inc(unsigned char *counter)
122
0
{
123
0
    unsigned int n = 8;
124
0
    u8 c;
125
126
0
    counter += 8;
127
0
    do {
128
0
        --n;
129
0
        c = counter[n];
130
0
        ++c;
131
0
        counter[n] = c;
132
0
        if (c)
133
0
            return;
134
0
    } while (n);
135
0
}
136
137
int CRYPTO_ccm128_encrypt(CCM128_CONTEXT *ctx,
138
                          const unsigned char *inp, unsigned char *out,
139
                          size_t len)
140
0
{
141
0
    size_t n;
142
0
    unsigned int i, L;
143
0
    unsigned char flags0 = ctx->nonce.c[0];
144
0
    block128_f block = ctx->block;
145
0
    void *key = ctx->key;
146
0
    union {
147
0
        u64 u[2];
148
0
        u8 c[16];
149
0
    } scratch;
150
151
0
    if (!(flags0 & 0x40))
152
0
        (*block) (ctx->nonce.c, ctx->cmac.c, key), ctx->blocks++;
153
154
0
    ctx->nonce.c[0] = L = flags0 & 7;
155
0
    for (n = 0, i = 15 - L; i < 15; ++i) {
156
0
        n |= ctx->nonce.c[i];
157
0
        ctx->nonce.c[i] = 0;
158
0
        n <<= 8;
159
0
    }
160
0
    n |= ctx->nonce.c[15];      /* reconstructed length */
161
0
    ctx->nonce.c[15] = 1;
162
163
0
    if (n != len)
164
0
        return -1;              /* length mismatch */
165
166
0
    ctx->blocks += ((len + 15) >> 3) | 1;
167
0
    if (ctx->blocks > (U64(1) << 61))
168
0
        return -2;              /* too much data */
169
170
0
    while (len >= 16) {
171
0
#if defined(STRICT_ALIGNMENT)
172
0
        union {
173
0
            u64 u[2];
174
0
            u8 c[16];
175
0
        } temp;
176
177
0
        memcpy(temp.c, inp, 16);
178
0
        ctx->cmac.u[0] ^= temp.u[0];
179
0
        ctx->cmac.u[1] ^= temp.u[1];
180
#else
181
        ctx->cmac.u[0] ^= ((u64_a1 *)inp)[0];
182
        ctx->cmac.u[1] ^= ((u64_a1 *)inp)[1];
183
#endif
184
0
        (*block) (ctx->cmac.c, ctx->cmac.c, key);
185
0
        (*block) (ctx->nonce.c, scratch.c, key);
186
0
        ctr64_inc(ctx->nonce.c);
187
0
#if defined(STRICT_ALIGNMENT)
188
0
        temp.u[0] ^= scratch.u[0];
189
0
        temp.u[1] ^= scratch.u[1];
190
0
        memcpy(out, temp.c, 16);
191
#else
192
        ((u64_a1 *)out)[0] = scratch.u[0] ^ ((u64_a1 *)inp)[0];
193
        ((u64_a1 *)out)[1] = scratch.u[1] ^ ((u64_a1 *)inp)[1];
194
#endif
195
0
        inp += 16;
196
0
        out += 16;
197
0
        len -= 16;
198
0
    }
199
200
0
    if (len) {
201
0
        for (i = 0; i < len; ++i)
202
0
            ctx->cmac.c[i] ^= inp[i];
203
0
        (*block) (ctx->cmac.c, ctx->cmac.c, key);
204
0
        (*block) (ctx->nonce.c, scratch.c, key);
205
0
        for (i = 0; i < len; ++i)
206
0
            out[i] = scratch.c[i] ^ inp[i];
207
0
    }
208
209
0
    for (i = 15 - L; i < 16; ++i)
210
0
        ctx->nonce.c[i] = 0;
211
212
0
    (*block) (ctx->nonce.c, scratch.c, key);
213
0
    ctx->cmac.u[0] ^= scratch.u[0];
214
0
    ctx->cmac.u[1] ^= scratch.u[1];
215
216
0
    ctx->nonce.c[0] = flags0;
217
218
0
    return 0;
219
0
}
220
221
int CRYPTO_ccm128_decrypt(CCM128_CONTEXT *ctx,
222
                          const unsigned char *inp, unsigned char *out,
223
                          size_t len)
224
0
{
225
0
    size_t n;
226
0
    unsigned int i, L;
227
0
    unsigned char flags0 = ctx->nonce.c[0];
228
0
    block128_f block = ctx->block;
229
0
    void *key = ctx->key;
230
0
    union {
231
0
        u64 u[2];
232
0
        u8 c[16];
233
0
    } scratch;
234
235
0
    if (!(flags0 & 0x40))
236
0
        (*block) (ctx->nonce.c, ctx->cmac.c, key);
237
238
0
    ctx->nonce.c[0] = L = flags0 & 7;
239
0
    for (n = 0, i = 15 - L; i < 15; ++i) {
240
0
        n |= ctx->nonce.c[i];
241
0
        ctx->nonce.c[i] = 0;
242
0
        n <<= 8;
243
0
    }
244
0
    n |= ctx->nonce.c[15];      /* reconstructed length */
245
0
    ctx->nonce.c[15] = 1;
246
247
0
    if (n != len)
248
0
        return -1;
249
250
0
    while (len >= 16) {
251
0
#if defined(STRICT_ALIGNMENT)
252
0
        union {
253
0
            u64 u[2];
254
0
            u8 c[16];
255
0
        } temp;
256
0
#endif
257
0
        (*block) (ctx->nonce.c, scratch.c, key);
258
0
        ctr64_inc(ctx->nonce.c);
259
0
#if defined(STRICT_ALIGNMENT)
260
0
        memcpy(temp.c, inp, 16);
261
0
        ctx->cmac.u[0] ^= (scratch.u[0] ^= temp.u[0]);
262
0
        ctx->cmac.u[1] ^= (scratch.u[1] ^= temp.u[1]);
263
0
        memcpy(out, scratch.c, 16);
264
#else
265
        ctx->cmac.u[0] ^= (((u64_a1 *)out)[0]
266
                            = scratch.u[0] ^ ((u64_a1 *)inp)[0]);
267
        ctx->cmac.u[1] ^= (((u64_a1 *)out)[1]
268
                            = scratch.u[1] ^ ((u64_a1 *)inp)[1]);
269
#endif
270
0
        (*block) (ctx->cmac.c, ctx->cmac.c, key);
271
272
0
        inp += 16;
273
0
        out += 16;
274
0
        len -= 16;
275
0
    }
276
277
0
    if (len) {
278
0
        (*block) (ctx->nonce.c, scratch.c, key);
279
0
        for (i = 0; i < len; ++i)
280
0
            ctx->cmac.c[i] ^= (out[i] = scratch.c[i] ^ inp[i]);
281
0
        (*block) (ctx->cmac.c, ctx->cmac.c, key);
282
0
    }
283
284
0
    for (i = 15 - L; i < 16; ++i)
285
0
        ctx->nonce.c[i] = 0;
286
287
0
    (*block) (ctx->nonce.c, scratch.c, key);
288
0
    ctx->cmac.u[0] ^= scratch.u[0];
289
0
    ctx->cmac.u[1] ^= scratch.u[1];
290
291
0
    ctx->nonce.c[0] = flags0;
292
293
0
    return 0;
294
0
}
295
296
static void ctr64_add(unsigned char *counter, size_t inc)
297
8.75k
{
298
8.75k
    size_t n = 8, val = 0;
299
300
8.75k
    counter += 8;
301
9.52k
    do {
302
9.52k
        --n;
303
9.52k
        val += counter[n] + (inc & 0xff);
304
9.52k
        counter[n] = (unsigned char)val;
305
9.52k
        val >>= 8;              /* carry bit */
306
9.52k
        inc >>= 8;
307
9.52k
    } while (n && (inc || val));
308
8.75k
}
309
310
int CRYPTO_ccm128_encrypt_ccm64(CCM128_CONTEXT *ctx,
311
                                const unsigned char *inp, unsigned char *out,
312
                                size_t len, ccm128_f stream)
313
541
{
314
541
    size_t n;
315
541
    unsigned int i, L;
316
541
    unsigned char flags0 = ctx->nonce.c[0];
317
541
    block128_f block = ctx->block;
318
541
    void *key = ctx->key;
319
541
    union {
320
541
        u64 u[2];
321
541
        u8 c[16];
322
541
    } scratch;
323
324
541
    if (!(flags0 & 0x40))
325
0
        (*block) (ctx->nonce.c, ctx->cmac.c, key), ctx->blocks++;
326
327
541
    ctx->nonce.c[0] = L = flags0 & 7;
328
1.62k
    for (n = 0, i = 15 - L; i < 15; ++i) {
329
1.08k
        n |= ctx->nonce.c[i];
330
1.08k
        ctx->nonce.c[i] = 0;
331
1.08k
        n <<= 8;
332
1.08k
    }
333
541
    n |= ctx->nonce.c[15];      /* reconstructed length */
334
541
    ctx->nonce.c[15] = 1;
335
336
541
    if (n != len)
337
0
        return -1;              /* length mismatch */
338
339
541
    ctx->blocks += ((len + 15) >> 3) | 1;
340
541
    if (ctx->blocks > (U64(1) << 61))
341
0
        return -2;              /* too much data */
342
343
541
    if ((n = len / 16)) {
344
367
        (*stream) (inp, out, n, key, ctx->nonce.c, ctx->cmac.c);
345
367
        n *= 16;
346
367
        inp += n;
347
367
        out += n;
348
367
        len -= n;
349
367
        if (len)
350
171
            ctr64_add(ctx->nonce.c, n / 16);
351
367
    }
352
353
541
    if (len) {
354
2.06k
        for (i = 0; i < len; ++i)
355
1.71k
            ctx->cmac.c[i] ^= inp[i];
356
345
        (*block) (ctx->cmac.c, ctx->cmac.c, key);
357
345
        (*block) (ctx->nonce.c, scratch.c, key);
358
2.06k
        for (i = 0; i < len; ++i)
359
1.71k
            out[i] = scratch.c[i] ^ inp[i];
360
345
    }
361
362
2.16k
    for (i = 15 - L; i < 16; ++i)
363
1.62k
        ctx->nonce.c[i] = 0;
364
365
541
    (*block) (ctx->nonce.c, scratch.c, key);
366
541
    ctx->cmac.u[0] ^= scratch.u[0];
367
541
    ctx->cmac.u[1] ^= scratch.u[1];
368
369
541
    ctx->nonce.c[0] = flags0;
370
371
541
    return 0;
372
541
}
373
374
int CRYPTO_ccm128_decrypt_ccm64(CCM128_CONTEXT *ctx,
375
                                const unsigned char *inp, unsigned char *out,
376
                                size_t len, ccm128_f stream)
377
37.7k
{
378
37.7k
    size_t n;
379
37.7k
    unsigned int i, L;
380
37.7k
    unsigned char flags0 = ctx->nonce.c[0];
381
37.7k
    block128_f block = ctx->block;
382
37.7k
    void *key = ctx->key;
383
37.7k
    union {
384
37.7k
        u64 u[2];
385
37.7k
        u8 c[16];
386
37.7k
    } scratch;
387
388
37.7k
    if (!(flags0 & 0x40))
389
0
        (*block) (ctx->nonce.c, ctx->cmac.c, key);
390
391
37.7k
    ctx->nonce.c[0] = L = flags0 & 7;
392
113k
    for (n = 0, i = 15 - L; i < 15; ++i) {
393
75.5k
        n |= ctx->nonce.c[i];
394
75.5k
        ctx->nonce.c[i] = 0;
395
75.5k
        n <<= 8;
396
75.5k
    }
397
37.7k
    n |= ctx->nonce.c[15];      /* reconstructed length */
398
37.7k
    ctx->nonce.c[15] = 1;
399
400
37.7k
    if (n != len)
401
0
        return -1;
402
403
37.7k
    if ((n = len / 16)) {
404
13.5k
        (*stream) (inp, out, n, key, ctx->nonce.c, ctx->cmac.c);
405
13.5k
        n *= 16;
406
13.5k
        inp += n;
407
13.5k
        out += n;
408
13.5k
        len -= n;
409
13.5k
        if (len)
410
8.58k
            ctr64_add(ctx->nonce.c, n / 16);
411
13.5k
    }
412
413
37.7k
    if (len) {
414
19.3k
        (*block) (ctx->nonce.c, scratch.c, key);
415
172k
        for (i = 0; i < len; ++i)
416
153k
            ctx->cmac.c[i] ^= (out[i] = scratch.c[i] ^ inp[i]);
417
19.3k
        (*block) (ctx->cmac.c, ctx->cmac.c, key);
418
19.3k
    }
419
420
151k
    for (i = 15 - L; i < 16; ++i)
421
113k
        ctx->nonce.c[i] = 0;
422
423
37.7k
    (*block) (ctx->nonce.c, scratch.c, key);
424
37.7k
    ctx->cmac.u[0] ^= scratch.u[0];
425
37.7k
    ctx->cmac.u[1] ^= scratch.u[1];
426
427
37.7k
    ctx->nonce.c[0] = flags0;
428
429
37.7k
    return 0;
430
37.7k
}
431
432
size_t CRYPTO_ccm128_tag(CCM128_CONTEXT *ctx, unsigned char *tag, size_t len)
433
38.2k
{
434
38.2k
    unsigned int M = (ctx->nonce.c[0] >> 3) & 7; /* the M parameter */
435
436
38.2k
    M *= 2;
437
38.2k
    M += 2;
438
38.2k
    if (len != M)
439
0
        return 0;
440
38.2k
    memcpy(tag, ctx->cmac.c, M);
441
38.2k
    return M;
442
38.2k
}