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