Coverage Report

Created: 2024-08-17 06:46

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