ccm128.c revision 296341
1/* ====================================================================
2 * Copyright (c) 2011 The OpenSSL Project.  All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in
13 *    the documentation and/or other materials provided with the
14 *    distribution.
15 *
16 * 3. All advertising materials mentioning features or use of this
17 *    software must display the following acknowledgment:
18 *    "This product includes software developed by the OpenSSL Project
19 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
20 *
21 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22 *    endorse or promote products derived from this software without
23 *    prior written permission. For written permission, please contact
24 *    openssl-core@openssl.org.
25 *
26 * 5. Products derived from this software may not be called "OpenSSL"
27 *    nor may "OpenSSL" appear in their names without prior written
28 *    permission of the OpenSSL Project.
29 *
30 * 6. Redistributions of any form whatsoever must retain the following
31 *    acknowledgment:
32 *    "This product includes software developed by the OpenSSL Project
33 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
34 *
35 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
36 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46 * OF THE POSSIBILITY OF SUCH DAMAGE.
47 * ====================================================================
48 */
49
50#include <openssl/crypto.h>
51#include "modes_lcl.h"
52#include <string.h>
53
54#ifndef MODES_DEBUG
55# ifndef NDEBUG
56#  define NDEBUG
57# endif
58#endif
59#include <assert.h>
60
61/*
62 * First you setup M and L parameters and pass the key schedule. This is
63 * called once per session setup...
64 */
65void CRYPTO_ccm128_init(CCM128_CONTEXT *ctx,
66                        unsigned int M, unsigned int L, void *key,
67                        block128_f block)
68{
69    memset(ctx->nonce.c, 0, sizeof(ctx->nonce.c));
70    ctx->nonce.c[0] = ((u8)(L - 1) & 7) | (u8)(((M - 2) / 2) & 7) << 3;
71    ctx->blocks = 0;
72    ctx->block = block;
73    ctx->key = key;
74}
75
76/* !!! Following interfaces are to be called *once* per packet !!! */
77
78/* Then you setup per-message nonce and pass the length of the message */
79int CRYPTO_ccm128_setiv(CCM128_CONTEXT *ctx,
80                        const unsigned char *nonce, size_t nlen, size_t mlen)
81{
82    unsigned int L = ctx->nonce.c[0] & 7; /* the L parameter */
83
84    if (nlen < (14 - L))
85        return -1;              /* nonce is too short */
86
87    if (sizeof(mlen) == 8 && L >= 3) {
88        ctx->nonce.c[8] = (u8)(mlen >> (56 % (sizeof(mlen) * 8)));
89        ctx->nonce.c[9] = (u8)(mlen >> (48 % (sizeof(mlen) * 8)));
90        ctx->nonce.c[10] = (u8)(mlen >> (40 % (sizeof(mlen) * 8)));
91        ctx->nonce.c[11] = (u8)(mlen >> (32 % (sizeof(mlen) * 8)));
92    } else
93        ctx->nonce.u[1] = 0;
94
95    ctx->nonce.c[12] = (u8)(mlen >> 24);
96    ctx->nonce.c[13] = (u8)(mlen >> 16);
97    ctx->nonce.c[14] = (u8)(mlen >> 8);
98    ctx->nonce.c[15] = (u8)mlen;
99
100    ctx->nonce.c[0] &= ~0x40;   /* clear Adata flag */
101    memcpy(&ctx->nonce.c[1], nonce, 14 - L);
102
103    return 0;
104}
105
106/* Then you pass additional authentication data, this is optional */
107void CRYPTO_ccm128_aad(CCM128_CONTEXT *ctx,
108                       const unsigned char *aad, size_t alen)
109{
110    unsigned int i;
111    block128_f block = ctx->block;
112
113    if (alen == 0)
114        return;
115
116    ctx->nonce.c[0] |= 0x40;    /* set Adata flag */
117    (*block) (ctx->nonce.c, ctx->cmac.c, ctx->key), ctx->blocks++;
118
119    if (alen < (0x10000 - 0x100)) {
120        ctx->cmac.c[0] ^= (u8)(alen >> 8);
121        ctx->cmac.c[1] ^= (u8)alen;
122        i = 2;
123    } else if (sizeof(alen) == 8
124               && alen >= (size_t)1 << (32 % (sizeof(alen) * 8))) {
125        ctx->cmac.c[0] ^= 0xFF;
126        ctx->cmac.c[1] ^= 0xFF;
127        ctx->cmac.c[2] ^= (u8)(alen >> (56 % (sizeof(alen) * 8)));
128        ctx->cmac.c[3] ^= (u8)(alen >> (48 % (sizeof(alen) * 8)));
129        ctx->cmac.c[4] ^= (u8)(alen >> (40 % (sizeof(alen) * 8)));
130        ctx->cmac.c[5] ^= (u8)(alen >> (32 % (sizeof(alen) * 8)));
131        ctx->cmac.c[6] ^= (u8)(alen >> 24);
132        ctx->cmac.c[7] ^= (u8)(alen >> 16);
133        ctx->cmac.c[8] ^= (u8)(alen >> 8);
134        ctx->cmac.c[9] ^= (u8)alen;
135        i = 10;
136    } else {
137        ctx->cmac.c[0] ^= 0xFF;
138        ctx->cmac.c[1] ^= 0xFE;
139        ctx->cmac.c[2] ^= (u8)(alen >> 24);
140        ctx->cmac.c[3] ^= (u8)(alen >> 16);
141        ctx->cmac.c[4] ^= (u8)(alen >> 8);
142        ctx->cmac.c[5] ^= (u8)alen;
143        i = 6;
144    }
145
146    do {
147        for (; i < 16 && alen; ++i, ++aad, --alen)
148            ctx->cmac.c[i] ^= *aad;
149        (*block) (ctx->cmac.c, ctx->cmac.c, ctx->key), ctx->blocks++;
150        i = 0;
151    } while (alen);
152}
153
154/* Finally you encrypt or decrypt the message */
155
156/*
157 * counter part of nonce may not be larger than L*8 bits, L is not larger
158 * than 8, therefore 64-bit counter...
159 */
160static void ctr64_inc(unsigned char *counter)
161{
162    unsigned int n = 8;
163    u8 c;
164
165    counter += 8;
166    do {
167        --n;
168        c = counter[n];
169        ++c;
170        counter[n] = c;
171        if (c)
172            return;
173    } while (n);
174}
175
176int CRYPTO_ccm128_encrypt(CCM128_CONTEXT *ctx,
177                          const unsigned char *inp, unsigned char *out,
178                          size_t len)
179{
180    size_t n;
181    unsigned int i, L;
182    unsigned char flags0 = ctx->nonce.c[0];
183    block128_f block = ctx->block;
184    void *key = ctx->key;
185    union {
186        u64 u[2];
187        u8 c[16];
188    } scratch;
189
190    if (!(flags0 & 0x40))
191        (*block) (ctx->nonce.c, ctx->cmac.c, key), ctx->blocks++;
192
193    ctx->nonce.c[0] = L = flags0 & 7;
194    for (n = 0, i = 15 - L; i < 15; ++i) {
195        n |= ctx->nonce.c[i];
196        ctx->nonce.c[i] = 0;
197        n <<= 8;
198    }
199    n |= ctx->nonce.c[15];      /* reconstructed length */
200    ctx->nonce.c[15] = 1;
201
202    if (n != len)
203        return -1;              /* length mismatch */
204
205    ctx->blocks += ((len + 15) >> 3) | 1;
206    if (ctx->blocks > (U64(1) << 61))
207        return -2;              /* too much data */
208
209    while (len >= 16) {
210#if defined(STRICT_ALIGNMENT)
211        union {
212            u64 u[2];
213            u8 c[16];
214        } temp;
215
216        memcpy(temp.c, inp, 16);
217        ctx->cmac.u[0] ^= temp.u[0];
218        ctx->cmac.u[1] ^= temp.u[1];
219#else
220        ctx->cmac.u[0] ^= ((u64 *)inp)[0];
221        ctx->cmac.u[1] ^= ((u64 *)inp)[1];
222#endif
223        (*block) (ctx->cmac.c, ctx->cmac.c, key);
224        (*block) (ctx->nonce.c, scratch.c, key);
225        ctr64_inc(ctx->nonce.c);
226#if defined(STRICT_ALIGNMENT)
227        temp.u[0] ^= scratch.u[0];
228        temp.u[1] ^= scratch.u[1];
229        memcpy(out, temp.c, 16);
230#else
231        ((u64 *)out)[0] = scratch.u[0] ^ ((u64 *)inp)[0];
232        ((u64 *)out)[1] = scratch.u[1] ^ ((u64 *)inp)[1];
233#endif
234        inp += 16;
235        out += 16;
236        len -= 16;
237    }
238
239    if (len) {
240        for (i = 0; i < len; ++i)
241            ctx->cmac.c[i] ^= inp[i];
242        (*block) (ctx->cmac.c, ctx->cmac.c, key);
243        (*block) (ctx->nonce.c, scratch.c, key);
244        for (i = 0; i < len; ++i)
245            out[i] = scratch.c[i] ^ inp[i];
246    }
247
248    for (i = 15 - L; i < 16; ++i)
249        ctx->nonce.c[i] = 0;
250
251    (*block) (ctx->nonce.c, scratch.c, key);
252    ctx->cmac.u[0] ^= scratch.u[0];
253    ctx->cmac.u[1] ^= scratch.u[1];
254
255    ctx->nonce.c[0] = flags0;
256
257    return 0;
258}
259
260int CRYPTO_ccm128_decrypt(CCM128_CONTEXT *ctx,
261                          const unsigned char *inp, unsigned char *out,
262                          size_t len)
263{
264    size_t n;
265    unsigned int i, L;
266    unsigned char flags0 = ctx->nonce.c[0];
267    block128_f block = ctx->block;
268    void *key = ctx->key;
269    union {
270        u64 u[2];
271        u8 c[16];
272    } scratch;
273
274    if (!(flags0 & 0x40))
275        (*block) (ctx->nonce.c, ctx->cmac.c, key);
276
277    ctx->nonce.c[0] = L = flags0 & 7;
278    for (n = 0, i = 15 - L; i < 15; ++i) {
279        n |= ctx->nonce.c[i];
280        ctx->nonce.c[i] = 0;
281        n <<= 8;
282    }
283    n |= ctx->nonce.c[15];      /* reconstructed length */
284    ctx->nonce.c[15] = 1;
285
286    if (n != len)
287        return -1;
288
289    while (len >= 16) {
290#if defined(STRICT_ALIGNMENT)
291        union {
292            u64 u[2];
293            u8 c[16];
294        } temp;
295#endif
296        (*block) (ctx->nonce.c, scratch.c, key);
297        ctr64_inc(ctx->nonce.c);
298#if defined(STRICT_ALIGNMENT)
299        memcpy(temp.c, inp, 16);
300        ctx->cmac.u[0] ^= (scratch.u[0] ^= temp.u[0]);
301        ctx->cmac.u[1] ^= (scratch.u[1] ^= temp.u[1]);
302        memcpy(out, scratch.c, 16);
303#else
304        ctx->cmac.u[0] ^= (((u64 *)out)[0] = scratch.u[0] ^ ((u64 *)inp)[0]);
305        ctx->cmac.u[1] ^= (((u64 *)out)[1] = scratch.u[1] ^ ((u64 *)inp)[1]);
306#endif
307        (*block) (ctx->cmac.c, ctx->cmac.c, key);
308
309        inp += 16;
310        out += 16;
311        len -= 16;
312    }
313
314    if (len) {
315        (*block) (ctx->nonce.c, scratch.c, key);
316        for (i = 0; i < len; ++i)
317            ctx->cmac.c[i] ^= (out[i] = scratch.c[i] ^ inp[i]);
318        (*block) (ctx->cmac.c, ctx->cmac.c, key);
319    }
320
321    for (i = 15 - L; i < 16; ++i)
322        ctx->nonce.c[i] = 0;
323
324    (*block) (ctx->nonce.c, scratch.c, key);
325    ctx->cmac.u[0] ^= scratch.u[0];
326    ctx->cmac.u[1] ^= scratch.u[1];
327
328    ctx->nonce.c[0] = flags0;
329
330    return 0;
331}
332
333static void ctr64_add(unsigned char *counter, size_t inc)
334{
335    size_t n = 8, val = 0;
336
337    counter += 8;
338    do {
339        --n;
340        val += counter[n] + (inc & 0xff);
341        counter[n] = (unsigned char)val;
342        val >>= 8;              /* carry bit */
343        inc >>= 8;
344    } while (n && (inc || val));
345}
346
347int CRYPTO_ccm128_encrypt_ccm64(CCM128_CONTEXT *ctx,
348                                const unsigned char *inp, unsigned char *out,
349                                size_t len, ccm128_f stream)
350{
351    size_t n;
352    unsigned int i, L;
353    unsigned char flags0 = ctx->nonce.c[0];
354    block128_f block = ctx->block;
355    void *key = ctx->key;
356    union {
357        u64 u[2];
358        u8 c[16];
359    } scratch;
360
361    if (!(flags0 & 0x40))
362        (*block) (ctx->nonce.c, ctx->cmac.c, key), ctx->blocks++;
363
364    ctx->nonce.c[0] = L = flags0 & 7;
365    for (n = 0, i = 15 - L; i < 15; ++i) {
366        n |= ctx->nonce.c[i];
367        ctx->nonce.c[i] = 0;
368        n <<= 8;
369    }
370    n |= ctx->nonce.c[15];      /* reconstructed length */
371    ctx->nonce.c[15] = 1;
372
373    if (n != len)
374        return -1;              /* length mismatch */
375
376    ctx->blocks += ((len + 15) >> 3) | 1;
377    if (ctx->blocks > (U64(1) << 61))
378        return -2;              /* too much data */
379
380    if ((n = len / 16)) {
381        (*stream) (inp, out, n, key, ctx->nonce.c, ctx->cmac.c);
382        n *= 16;
383        inp += n;
384        out += n;
385        len -= n;
386        if (len)
387            ctr64_add(ctx->nonce.c, n / 16);
388    }
389
390    if (len) {
391        for (i = 0; i < len; ++i)
392            ctx->cmac.c[i] ^= inp[i];
393        (*block) (ctx->cmac.c, ctx->cmac.c, key);
394        (*block) (ctx->nonce.c, scratch.c, key);
395        for (i = 0; i < len; ++i)
396            out[i] = scratch.c[i] ^ inp[i];
397    }
398
399    for (i = 15 - L; i < 16; ++i)
400        ctx->nonce.c[i] = 0;
401
402    (*block) (ctx->nonce.c, scratch.c, key);
403    ctx->cmac.u[0] ^= scratch.u[0];
404    ctx->cmac.u[1] ^= scratch.u[1];
405
406    ctx->nonce.c[0] = flags0;
407
408    return 0;
409}
410
411int CRYPTO_ccm128_decrypt_ccm64(CCM128_CONTEXT *ctx,
412                                const unsigned char *inp, unsigned char *out,
413                                size_t len, ccm128_f stream)
414{
415    size_t n;
416    unsigned int i, L;
417    unsigned char flags0 = ctx->nonce.c[0];
418    block128_f block = ctx->block;
419    void *key = ctx->key;
420    union {
421        u64 u[2];
422        u8 c[16];
423    } scratch;
424
425    if (!(flags0 & 0x40))
426        (*block) (ctx->nonce.c, ctx->cmac.c, key);
427
428    ctx->nonce.c[0] = L = flags0 & 7;
429    for (n = 0, i = 15 - L; i < 15; ++i) {
430        n |= ctx->nonce.c[i];
431        ctx->nonce.c[i] = 0;
432        n <<= 8;
433    }
434    n |= ctx->nonce.c[15];      /* reconstructed length */
435    ctx->nonce.c[15] = 1;
436
437    if (n != len)
438        return -1;
439
440    if ((n = len / 16)) {
441        (*stream) (inp, out, n, key, ctx->nonce.c, ctx->cmac.c);
442        n *= 16;
443        inp += n;
444        out += n;
445        len -= n;
446        if (len)
447            ctr64_add(ctx->nonce.c, n / 16);
448    }
449
450    if (len) {
451        (*block) (ctx->nonce.c, scratch.c, key);
452        for (i = 0; i < len; ++i)
453            ctx->cmac.c[i] ^= (out[i] = scratch.c[i] ^ inp[i]);
454        (*block) (ctx->cmac.c, ctx->cmac.c, key);
455    }
456
457    for (i = 15 - L; i < 16; ++i)
458        ctx->nonce.c[i] = 0;
459
460    (*block) (ctx->nonce.c, scratch.c, key);
461    ctx->cmac.u[0] ^= scratch.u[0];
462    ctx->cmac.u[1] ^= scratch.u[1];
463
464    ctx->nonce.c[0] = flags0;
465
466    return 0;
467}
468
469size_t CRYPTO_ccm128_tag(CCM128_CONTEXT *ctx, unsigned char *tag, size_t len)
470{
471    unsigned int M = (ctx->nonce.c[0] >> 3) & 7; /* the M parameter */
472
473    M *= 2;
474    M += 2;
475    if (len < M)
476        return 0;
477    memcpy(tag, ctx->cmac.c, M);
478    return M;
479}
480