Avoid undefined behavior with unaligned accesses
[openssl.git] / crypto / modes / ccm128.c
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 #ifndef STRICT_ALIGNMENT
15 # ifdef __GNUC__
16 typedef u64 u64_a1 __attribute((__aligned__(1)));
17 # else
18 typedef 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  */
26 void 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 */
40 int 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 */
68 void 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  */
121 static 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
137 int 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
221 int 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
296 static 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
310 int 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
374 int 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
432 size_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 }