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