1238384Sjkim/* ====================================================================
2238384Sjkim * Copyright (c) 2011 The OpenSSL Project.  All rights reserved.
3238384Sjkim *
4238384Sjkim * Redistribution and use in source and binary forms, with or without
5238384Sjkim * modification, are permitted provided that the following conditions
6238384Sjkim * are met:
7238384Sjkim *
8238384Sjkim * 1. Redistributions of source code must retain the above copyright
9296341Sdelphij *    notice, this list of conditions and the following disclaimer.
10238384Sjkim *
11238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright
12238384Sjkim *    notice, this list of conditions and the following disclaimer in
13238384Sjkim *    the documentation and/or other materials provided with the
14238384Sjkim *    distribution.
15238384Sjkim *
16238384Sjkim * 3. All advertising materials mentioning features or use of this
17238384Sjkim *    software must display the following acknowledgment:
18238384Sjkim *    "This product includes software developed by the OpenSSL Project
19238384Sjkim *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
20238384Sjkim *
21238384Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22238384Sjkim *    endorse or promote products derived from this software without
23238384Sjkim *    prior written permission. For written permission, please contact
24238384Sjkim *    openssl-core@openssl.org.
25238384Sjkim *
26238384Sjkim * 5. Products derived from this software may not be called "OpenSSL"
27238384Sjkim *    nor may "OpenSSL" appear in their names without prior written
28238384Sjkim *    permission of the OpenSSL Project.
29238384Sjkim *
30238384Sjkim * 6. Redistributions of any form whatsoever must retain the following
31238384Sjkim *    acknowledgment:
32238384Sjkim *    "This product includes software developed by the OpenSSL Project
33238384Sjkim *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
34238384Sjkim *
35238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
36238384Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38238384Sjkim * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
39238384Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40238384Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41238384Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42238384Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44238384Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45238384Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46238384Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE.
47238384Sjkim * ====================================================================
48238384Sjkim */
49238384Sjkim
50238384Sjkim#include <openssl/crypto.h>
51238384Sjkim#include "modes_lcl.h"
52238384Sjkim#include <string.h>
53238384Sjkim
54238384Sjkim#ifndef MODES_DEBUG
55238384Sjkim# ifndef NDEBUG
56238384Sjkim#  define NDEBUG
57238384Sjkim# endif
58238384Sjkim#endif
59238384Sjkim#include <assert.h>
60238384Sjkim
61296341Sdelphij/*
62296341Sdelphij * First you setup M and L parameters and pass the key schedule. This is
63296341Sdelphij * called once per session setup...
64296341Sdelphij */
65238384Sjkimvoid CRYPTO_ccm128_init(CCM128_CONTEXT *ctx,
66296341Sdelphij                        unsigned int M, unsigned int L, void *key,
67296341Sdelphij                        block128_f block)
68238384Sjkim{
69296341Sdelphij    memset(ctx->nonce.c, 0, sizeof(ctx->nonce.c));
70296341Sdelphij    ctx->nonce.c[0] = ((u8)(L - 1) & 7) | (u8)(((M - 2) / 2) & 7) << 3;
71296341Sdelphij    ctx->blocks = 0;
72296341Sdelphij    ctx->block = block;
73296341Sdelphij    ctx->key = key;
74238384Sjkim}
75238384Sjkim
76238384Sjkim/* !!! Following interfaces are to be called *once* per packet !!! */
77238384Sjkim
78238384Sjkim/* Then you setup per-message nonce and pass the length of the message */
79238384Sjkimint CRYPTO_ccm128_setiv(CCM128_CONTEXT *ctx,
80296341Sdelphij                        const unsigned char *nonce, size_t nlen, size_t mlen)
81238384Sjkim{
82296341Sdelphij    unsigned int L = ctx->nonce.c[0] & 7; /* the L parameter */
83238384Sjkim
84296341Sdelphij    if (nlen < (14 - L))
85296341Sdelphij        return -1;              /* nonce is too short */
86238384Sjkim
87296341Sdelphij    if (sizeof(mlen) == 8 && L >= 3) {
88296341Sdelphij        ctx->nonce.c[8] = (u8)(mlen >> (56 % (sizeof(mlen) * 8)));
89296341Sdelphij        ctx->nonce.c[9] = (u8)(mlen >> (48 % (sizeof(mlen) * 8)));
90296341Sdelphij        ctx->nonce.c[10] = (u8)(mlen >> (40 % (sizeof(mlen) * 8)));
91296341Sdelphij        ctx->nonce.c[11] = (u8)(mlen >> (32 % (sizeof(mlen) * 8)));
92296341Sdelphij    } else
93296341Sdelphij        ctx->nonce.u[1] = 0;
94238384Sjkim
95296341Sdelphij    ctx->nonce.c[12] = (u8)(mlen >> 24);
96296341Sdelphij    ctx->nonce.c[13] = (u8)(mlen >> 16);
97296341Sdelphij    ctx->nonce.c[14] = (u8)(mlen >> 8);
98296341Sdelphij    ctx->nonce.c[15] = (u8)mlen;
99238384Sjkim
100296341Sdelphij    ctx->nonce.c[0] &= ~0x40;   /* clear Adata flag */
101296341Sdelphij    memcpy(&ctx->nonce.c[1], nonce, 14 - L);
102238384Sjkim
103296341Sdelphij    return 0;
104238384Sjkim}
105238384Sjkim
106238384Sjkim/* Then you pass additional authentication data, this is optional */
107238384Sjkimvoid CRYPTO_ccm128_aad(CCM128_CONTEXT *ctx,
108296341Sdelphij                       const unsigned char *aad, size_t alen)
109296341Sdelphij{
110296341Sdelphij    unsigned int i;
111296341Sdelphij    block128_f block = ctx->block;
112238384Sjkim
113296341Sdelphij    if (alen == 0)
114296341Sdelphij        return;
115238384Sjkim
116296341Sdelphij    ctx->nonce.c[0] |= 0x40;    /* set Adata flag */
117296341Sdelphij    (*block) (ctx->nonce.c, ctx->cmac.c, ctx->key), ctx->blocks++;
118238384Sjkim
119296341Sdelphij    if (alen < (0x10000 - 0x100)) {
120296341Sdelphij        ctx->cmac.c[0] ^= (u8)(alen >> 8);
121296341Sdelphij        ctx->cmac.c[1] ^= (u8)alen;
122296341Sdelphij        i = 2;
123296341Sdelphij    } else if (sizeof(alen) == 8
124296341Sdelphij               && alen >= (size_t)1 << (32 % (sizeof(alen) * 8))) {
125296341Sdelphij        ctx->cmac.c[0] ^= 0xFF;
126296341Sdelphij        ctx->cmac.c[1] ^= 0xFF;
127296341Sdelphij        ctx->cmac.c[2] ^= (u8)(alen >> (56 % (sizeof(alen) * 8)));
128296341Sdelphij        ctx->cmac.c[3] ^= (u8)(alen >> (48 % (sizeof(alen) * 8)));
129296341Sdelphij        ctx->cmac.c[4] ^= (u8)(alen >> (40 % (sizeof(alen) * 8)));
130296341Sdelphij        ctx->cmac.c[5] ^= (u8)(alen >> (32 % (sizeof(alen) * 8)));
131296341Sdelphij        ctx->cmac.c[6] ^= (u8)(alen >> 24);
132296341Sdelphij        ctx->cmac.c[7] ^= (u8)(alen >> 16);
133296341Sdelphij        ctx->cmac.c[8] ^= (u8)(alen >> 8);
134296341Sdelphij        ctx->cmac.c[9] ^= (u8)alen;
135296341Sdelphij        i = 10;
136296341Sdelphij    } else {
137296341Sdelphij        ctx->cmac.c[0] ^= 0xFF;
138296341Sdelphij        ctx->cmac.c[1] ^= 0xFE;
139296341Sdelphij        ctx->cmac.c[2] ^= (u8)(alen >> 24);
140296341Sdelphij        ctx->cmac.c[3] ^= (u8)(alen >> 16);
141296341Sdelphij        ctx->cmac.c[4] ^= (u8)(alen >> 8);
142296341Sdelphij        ctx->cmac.c[5] ^= (u8)alen;
143296341Sdelphij        i = 6;
144296341Sdelphij    }
145238384Sjkim
146296341Sdelphij    do {
147296341Sdelphij        for (; i < 16 && alen; ++i, ++aad, --alen)
148296341Sdelphij            ctx->cmac.c[i] ^= *aad;
149296341Sdelphij        (*block) (ctx->cmac.c, ctx->cmac.c, ctx->key), ctx->blocks++;
150296341Sdelphij        i = 0;
151296341Sdelphij    } while (alen);
152238384Sjkim}
153238384Sjkim
154238384Sjkim/* Finally you encrypt or decrypt the message */
155238384Sjkim
156296341Sdelphij/*
157296341Sdelphij * counter part of nonce may not be larger than L*8 bits, L is not larger
158296341Sdelphij * than 8, therefore 64-bit counter...
159296341Sdelphij */
160296341Sdelphijstatic void ctr64_inc(unsigned char *counter)
161296341Sdelphij{
162296341Sdelphij    unsigned int n = 8;
163296341Sdelphij    u8 c;
164238384Sjkim
165296341Sdelphij    counter += 8;
166296341Sdelphij    do {
167296341Sdelphij        --n;
168296341Sdelphij        c = counter[n];
169296341Sdelphij        ++c;
170296341Sdelphij        counter[n] = c;
171296341Sdelphij        if (c)
172296341Sdelphij            return;
173296341Sdelphij    } while (n);
174238384Sjkim}
175238384Sjkim
176238384Sjkimint CRYPTO_ccm128_encrypt(CCM128_CONTEXT *ctx,
177296341Sdelphij                          const unsigned char *inp, unsigned char *out,
178296341Sdelphij                          size_t len)
179238384Sjkim{
180296341Sdelphij    size_t n;
181296341Sdelphij    unsigned int i, L;
182296341Sdelphij    unsigned char flags0 = ctx->nonce.c[0];
183296341Sdelphij    block128_f block = ctx->block;
184296341Sdelphij    void *key = ctx->key;
185296341Sdelphij    union {
186296341Sdelphij        u64 u[2];
187296341Sdelphij        u8 c[16];
188296341Sdelphij    } scratch;
189238384Sjkim
190296341Sdelphij    if (!(flags0 & 0x40))
191296341Sdelphij        (*block) (ctx->nonce.c, ctx->cmac.c, key), ctx->blocks++;
192238384Sjkim
193296341Sdelphij    ctx->nonce.c[0] = L = flags0 & 7;
194296341Sdelphij    for (n = 0, i = 15 - L; i < 15; ++i) {
195296341Sdelphij        n |= ctx->nonce.c[i];
196296341Sdelphij        ctx->nonce.c[i] = 0;
197296341Sdelphij        n <<= 8;
198296341Sdelphij    }
199296341Sdelphij    n |= ctx->nonce.c[15];      /* reconstructed length */
200296341Sdelphij    ctx->nonce.c[15] = 1;
201238384Sjkim
202296341Sdelphij    if (n != len)
203296341Sdelphij        return -1;              /* length mismatch */
204238384Sjkim
205296341Sdelphij    ctx->blocks += ((len + 15) >> 3) | 1;
206296341Sdelphij    if (ctx->blocks > (U64(1) << 61))
207296341Sdelphij        return -2;              /* too much data */
208238384Sjkim
209296341Sdelphij    while (len >= 16) {
210238384Sjkim#if defined(STRICT_ALIGNMENT)
211296341Sdelphij        union {
212296341Sdelphij            u64 u[2];
213296341Sdelphij            u8 c[16];
214296341Sdelphij        } temp;
215238384Sjkim
216296341Sdelphij        memcpy(temp.c, inp, 16);
217296341Sdelphij        ctx->cmac.u[0] ^= temp.u[0];
218296341Sdelphij        ctx->cmac.u[1] ^= temp.u[1];
219238384Sjkim#else
220296341Sdelphij        ctx->cmac.u[0] ^= ((u64 *)inp)[0];
221296341Sdelphij        ctx->cmac.u[1] ^= ((u64 *)inp)[1];
222238384Sjkim#endif
223296341Sdelphij        (*block) (ctx->cmac.c, ctx->cmac.c, key);
224296341Sdelphij        (*block) (ctx->nonce.c, scratch.c, key);
225296341Sdelphij        ctr64_inc(ctx->nonce.c);
226238384Sjkim#if defined(STRICT_ALIGNMENT)
227296341Sdelphij        temp.u[0] ^= scratch.u[0];
228296341Sdelphij        temp.u[1] ^= scratch.u[1];
229296341Sdelphij        memcpy(out, temp.c, 16);
230238384Sjkim#else
231296341Sdelphij        ((u64 *)out)[0] = scratch.u[0] ^ ((u64 *)inp)[0];
232296341Sdelphij        ((u64 *)out)[1] = scratch.u[1] ^ ((u64 *)inp)[1];
233238384Sjkim#endif
234296341Sdelphij        inp += 16;
235296341Sdelphij        out += 16;
236296341Sdelphij        len -= 16;
237296341Sdelphij    }
238238384Sjkim
239296341Sdelphij    if (len) {
240296341Sdelphij        for (i = 0; i < len; ++i)
241296341Sdelphij            ctx->cmac.c[i] ^= inp[i];
242296341Sdelphij        (*block) (ctx->cmac.c, ctx->cmac.c, key);
243296341Sdelphij        (*block) (ctx->nonce.c, scratch.c, key);
244296341Sdelphij        for (i = 0; i < len; ++i)
245296341Sdelphij            out[i] = scratch.c[i] ^ inp[i];
246296341Sdelphij    }
247238384Sjkim
248296341Sdelphij    for (i = 15 - L; i < 16; ++i)
249296341Sdelphij        ctx->nonce.c[i] = 0;
250238384Sjkim
251296341Sdelphij    (*block) (ctx->nonce.c, scratch.c, key);
252296341Sdelphij    ctx->cmac.u[0] ^= scratch.u[0];
253296341Sdelphij    ctx->cmac.u[1] ^= scratch.u[1];
254238384Sjkim
255296341Sdelphij    ctx->nonce.c[0] = flags0;
256238384Sjkim
257296341Sdelphij    return 0;
258238384Sjkim}
259238384Sjkim
260238384Sjkimint CRYPTO_ccm128_decrypt(CCM128_CONTEXT *ctx,
261296341Sdelphij                          const unsigned char *inp, unsigned char *out,
262296341Sdelphij                          size_t len)
263238384Sjkim{
264296341Sdelphij    size_t n;
265296341Sdelphij    unsigned int i, L;
266296341Sdelphij    unsigned char flags0 = ctx->nonce.c[0];
267296341Sdelphij    block128_f block = ctx->block;
268296341Sdelphij    void *key = ctx->key;
269296341Sdelphij    union {
270296341Sdelphij        u64 u[2];
271296341Sdelphij        u8 c[16];
272296341Sdelphij    } scratch;
273238384Sjkim
274296341Sdelphij    if (!(flags0 & 0x40))
275296341Sdelphij        (*block) (ctx->nonce.c, ctx->cmac.c, key);
276238384Sjkim
277296341Sdelphij    ctx->nonce.c[0] = L = flags0 & 7;
278296341Sdelphij    for (n = 0, i = 15 - L; i < 15; ++i) {
279296341Sdelphij        n |= ctx->nonce.c[i];
280296341Sdelphij        ctx->nonce.c[i] = 0;
281296341Sdelphij        n <<= 8;
282296341Sdelphij    }
283296341Sdelphij    n |= ctx->nonce.c[15];      /* reconstructed length */
284296341Sdelphij    ctx->nonce.c[15] = 1;
285238384Sjkim
286296341Sdelphij    if (n != len)
287296341Sdelphij        return -1;
288238384Sjkim
289296341Sdelphij    while (len >= 16) {
290238384Sjkim#if defined(STRICT_ALIGNMENT)
291296341Sdelphij        union {
292296341Sdelphij            u64 u[2];
293296341Sdelphij            u8 c[16];
294296341Sdelphij        } temp;
295238384Sjkim#endif
296296341Sdelphij        (*block) (ctx->nonce.c, scratch.c, key);
297296341Sdelphij        ctr64_inc(ctx->nonce.c);
298238384Sjkim#if defined(STRICT_ALIGNMENT)
299296341Sdelphij        memcpy(temp.c, inp, 16);
300296341Sdelphij        ctx->cmac.u[0] ^= (scratch.u[0] ^= temp.u[0]);
301296341Sdelphij        ctx->cmac.u[1] ^= (scratch.u[1] ^= temp.u[1]);
302296341Sdelphij        memcpy(out, scratch.c, 16);
303238384Sjkim#else
304296341Sdelphij        ctx->cmac.u[0] ^= (((u64 *)out)[0] = scratch.u[0] ^ ((u64 *)inp)[0]);
305296341Sdelphij        ctx->cmac.u[1] ^= (((u64 *)out)[1] = scratch.u[1] ^ ((u64 *)inp)[1]);
306238384Sjkim#endif
307296341Sdelphij        (*block) (ctx->cmac.c, ctx->cmac.c, key);
308238384Sjkim
309296341Sdelphij        inp += 16;
310296341Sdelphij        out += 16;
311296341Sdelphij        len -= 16;
312296341Sdelphij    }
313238384Sjkim
314296341Sdelphij    if (len) {
315296341Sdelphij        (*block) (ctx->nonce.c, scratch.c, key);
316296341Sdelphij        for (i = 0; i < len; ++i)
317296341Sdelphij            ctx->cmac.c[i] ^= (out[i] = scratch.c[i] ^ inp[i]);
318296341Sdelphij        (*block) (ctx->cmac.c, ctx->cmac.c, key);
319296341Sdelphij    }
320238384Sjkim
321296341Sdelphij    for (i = 15 - L; i < 16; ++i)
322296341Sdelphij        ctx->nonce.c[i] = 0;
323238384Sjkim
324296341Sdelphij    (*block) (ctx->nonce.c, scratch.c, key);
325296341Sdelphij    ctx->cmac.u[0] ^= scratch.u[0];
326296341Sdelphij    ctx->cmac.u[1] ^= scratch.u[1];
327238384Sjkim
328296341Sdelphij    ctx->nonce.c[0] = flags0;
329238384Sjkim
330296341Sdelphij    return 0;
331238384Sjkim}
332238384Sjkim
333296341Sdelphijstatic void ctr64_add(unsigned char *counter, size_t inc)
334296341Sdelphij{
335296341Sdelphij    size_t n = 8, val = 0;
336238384Sjkim
337296341Sdelphij    counter += 8;
338296341Sdelphij    do {
339296341Sdelphij        --n;
340296341Sdelphij        val += counter[n] + (inc & 0xff);
341296341Sdelphij        counter[n] = (unsigned char)val;
342296341Sdelphij        val >>= 8;              /* carry bit */
343296341Sdelphij        inc >>= 8;
344296341Sdelphij    } while (n && (inc || val));
345238384Sjkim}
346238384Sjkim
347238384Sjkimint CRYPTO_ccm128_encrypt_ccm64(CCM128_CONTEXT *ctx,
348296341Sdelphij                                const unsigned char *inp, unsigned char *out,
349296341Sdelphij                                size_t len, ccm128_f stream)
350238384Sjkim{
351296341Sdelphij    size_t n;
352296341Sdelphij    unsigned int i, L;
353296341Sdelphij    unsigned char flags0 = ctx->nonce.c[0];
354296341Sdelphij    block128_f block = ctx->block;
355296341Sdelphij    void *key = ctx->key;
356296341Sdelphij    union {
357296341Sdelphij        u64 u[2];
358296341Sdelphij        u8 c[16];
359296341Sdelphij    } scratch;
360238384Sjkim
361296341Sdelphij    if (!(flags0 & 0x40))
362296341Sdelphij        (*block) (ctx->nonce.c, ctx->cmac.c, key), ctx->blocks++;
363238384Sjkim
364296341Sdelphij    ctx->nonce.c[0] = L = flags0 & 7;
365296341Sdelphij    for (n = 0, i = 15 - L; i < 15; ++i) {
366296341Sdelphij        n |= ctx->nonce.c[i];
367296341Sdelphij        ctx->nonce.c[i] = 0;
368296341Sdelphij        n <<= 8;
369296341Sdelphij    }
370296341Sdelphij    n |= ctx->nonce.c[15];      /* reconstructed length */
371296341Sdelphij    ctx->nonce.c[15] = 1;
372238384Sjkim
373296341Sdelphij    if (n != len)
374296341Sdelphij        return -1;              /* length mismatch */
375238384Sjkim
376296341Sdelphij    ctx->blocks += ((len + 15) >> 3) | 1;
377296341Sdelphij    if (ctx->blocks > (U64(1) << 61))
378296341Sdelphij        return -2;              /* too much data */
379238384Sjkim
380296341Sdelphij    if ((n = len / 16)) {
381296341Sdelphij        (*stream) (inp, out, n, key, ctx->nonce.c, ctx->cmac.c);
382296341Sdelphij        n *= 16;
383296341Sdelphij        inp += n;
384296341Sdelphij        out += n;
385296341Sdelphij        len -= n;
386296341Sdelphij        if (len)
387296341Sdelphij            ctr64_add(ctx->nonce.c, n / 16);
388296341Sdelphij    }
389238384Sjkim
390296341Sdelphij    if (len) {
391296341Sdelphij        for (i = 0; i < len; ++i)
392296341Sdelphij            ctx->cmac.c[i] ^= inp[i];
393296341Sdelphij        (*block) (ctx->cmac.c, ctx->cmac.c, key);
394296341Sdelphij        (*block) (ctx->nonce.c, scratch.c, key);
395296341Sdelphij        for (i = 0; i < len; ++i)
396296341Sdelphij            out[i] = scratch.c[i] ^ inp[i];
397296341Sdelphij    }
398238384Sjkim
399296341Sdelphij    for (i = 15 - L; i < 16; ++i)
400296341Sdelphij        ctx->nonce.c[i] = 0;
401238384Sjkim
402296341Sdelphij    (*block) (ctx->nonce.c, scratch.c, key);
403296341Sdelphij    ctx->cmac.u[0] ^= scratch.u[0];
404296341Sdelphij    ctx->cmac.u[1] ^= scratch.u[1];
405238384Sjkim
406296341Sdelphij    ctx->nonce.c[0] = flags0;
407238384Sjkim
408296341Sdelphij    return 0;
409238384Sjkim}
410238384Sjkim
411238384Sjkimint CRYPTO_ccm128_decrypt_ccm64(CCM128_CONTEXT *ctx,
412296341Sdelphij                                const unsigned char *inp, unsigned char *out,
413296341Sdelphij                                size_t len, ccm128_f stream)
414238384Sjkim{
415296341Sdelphij    size_t n;
416296341Sdelphij    unsigned int i, L;
417296341Sdelphij    unsigned char flags0 = ctx->nonce.c[0];
418296341Sdelphij    block128_f block = ctx->block;
419296341Sdelphij    void *key = ctx->key;
420296341Sdelphij    union {
421296341Sdelphij        u64 u[2];
422296341Sdelphij        u8 c[16];
423296341Sdelphij    } scratch;
424238384Sjkim
425296341Sdelphij    if (!(flags0 & 0x40))
426296341Sdelphij        (*block) (ctx->nonce.c, ctx->cmac.c, key);
427238384Sjkim
428296341Sdelphij    ctx->nonce.c[0] = L = flags0 & 7;
429296341Sdelphij    for (n = 0, i = 15 - L; i < 15; ++i) {
430296341Sdelphij        n |= ctx->nonce.c[i];
431296341Sdelphij        ctx->nonce.c[i] = 0;
432296341Sdelphij        n <<= 8;
433296341Sdelphij    }
434296341Sdelphij    n |= ctx->nonce.c[15];      /* reconstructed length */
435296341Sdelphij    ctx->nonce.c[15] = 1;
436238384Sjkim
437296341Sdelphij    if (n != len)
438296341Sdelphij        return -1;
439238384Sjkim
440296341Sdelphij    if ((n = len / 16)) {
441296341Sdelphij        (*stream) (inp, out, n, key, ctx->nonce.c, ctx->cmac.c);
442296341Sdelphij        n *= 16;
443296341Sdelphij        inp += n;
444296341Sdelphij        out += n;
445296341Sdelphij        len -= n;
446296341Sdelphij        if (len)
447296341Sdelphij            ctr64_add(ctx->nonce.c, n / 16);
448296341Sdelphij    }
449238384Sjkim
450296341Sdelphij    if (len) {
451296341Sdelphij        (*block) (ctx->nonce.c, scratch.c, key);
452296341Sdelphij        for (i = 0; i < len; ++i)
453296341Sdelphij            ctx->cmac.c[i] ^= (out[i] = scratch.c[i] ^ inp[i]);
454296341Sdelphij        (*block) (ctx->cmac.c, ctx->cmac.c, key);
455296341Sdelphij    }
456238384Sjkim
457296341Sdelphij    for (i = 15 - L; i < 16; ++i)
458296341Sdelphij        ctx->nonce.c[i] = 0;
459238384Sjkim
460296341Sdelphij    (*block) (ctx->nonce.c, scratch.c, key);
461296341Sdelphij    ctx->cmac.u[0] ^= scratch.u[0];
462296341Sdelphij    ctx->cmac.u[1] ^= scratch.u[1];
463238384Sjkim
464296341Sdelphij    ctx->nonce.c[0] = flags0;
465238384Sjkim
466296341Sdelphij    return 0;
467238384Sjkim}
468238384Sjkim
469296341Sdelphijsize_t CRYPTO_ccm128_tag(CCM128_CONTEXT *ctx, unsigned char *tag, size_t len)
470296341Sdelphij{
471296341Sdelphij    unsigned int M = (ctx->nonce.c[0] >> 3) & 7; /* the M parameter */
472238384Sjkim
473296341Sdelphij    M *= 2;
474296341Sdelphij    M += 2;
475296341Sdelphij    if (len < M)
476296341Sdelphij        return 0;
477296341Sdelphij    memcpy(tag, ctx->cmac.c, M);
478296341Sdelphij    return M;
479238384Sjkim}
480