Line data Source code
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 : */
65 0 : void CRYPTO_ccm128_init(CCM128_CONTEXT *ctx,
66 : unsigned int M, unsigned int L, void *key,
67 : block128_f block)
68 : {
69 0 : memset(ctx->nonce.c, 0, sizeof(ctx->nonce.c));
70 0 : ctx->nonce.c[0] = ((u8)(L - 1) & 7) | (u8)(((M - 2) / 2) & 7) << 3;
71 0 : ctx->blocks = 0;
72 0 : ctx->block = block;
73 0 : ctx->key = key;
74 0 : }
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 */
79 0 : int CRYPTO_ccm128_setiv(CCM128_CONTEXT *ctx,
80 : const unsigned char *nonce, size_t nlen, size_t mlen)
81 : {
82 0 : unsigned int L = ctx->nonce.c[0] & 7; /* the L parameter */
83 :
84 0 : if (nlen < (14 - L))
85 : return -1; /* nonce is too short */
86 :
87 0 : if (sizeof(mlen) == 8 && L >= 3) {
88 0 : ctx->nonce.c[8] = (u8)(mlen >> (56 % (sizeof(mlen) * 8)));
89 0 : ctx->nonce.c[9] = (u8)(mlen >> (48 % (sizeof(mlen) * 8)));
90 0 : ctx->nonce.c[10] = (u8)(mlen >> (40 % (sizeof(mlen) * 8)));
91 0 : ctx->nonce.c[11] = (u8)(mlen >> (32 % (sizeof(mlen) * 8)));
92 : } else
93 0 : ctx->nonce.u[1] = 0;
94 :
95 0 : ctx->nonce.c[12] = (u8)(mlen >> 24);
96 0 : ctx->nonce.c[13] = (u8)(mlen >> 16);
97 0 : ctx->nonce.c[14] = (u8)(mlen >> 8);
98 0 : ctx->nonce.c[15] = (u8)mlen;
99 :
100 0 : ctx->nonce.c[0] &= ~0x40; /* clear Adata flag */
101 0 : memcpy(&ctx->nonce.c[1], nonce, 14 - L);
102 :
103 0 : return 0;
104 : }
105 :
106 : /* Then you pass additional authentication data, this is optional */
107 0 : void CRYPTO_ccm128_aad(CCM128_CONTEXT *ctx,
108 : const unsigned char *aad, size_t alen)
109 : {
110 : unsigned int i;
111 0 : block128_f block = ctx->block;
112 :
113 0 : if (alen == 0)
114 0 : return;
115 :
116 0 : ctx->nonce.c[0] |= 0x40; /* set Adata flag */
117 0 : (*block) (ctx->nonce.c, ctx->cmac.c, ctx->key), ctx->blocks++;
118 :
119 0 : if (alen < (0x10000 - 0x100)) {
120 0 : ctx->cmac.c[0] ^= (u8)(alen >> 8);
121 0 : ctx->cmac.c[1] ^= (u8)alen;
122 : i = 2;
123 0 : } else if (sizeof(alen) == 8
124 : && alen >= (size_t)1 << (32 % (sizeof(alen) * 8))) {
125 0 : ctx->cmac.c[0] ^= 0xFF;
126 0 : ctx->cmac.c[1] ^= 0xFF;
127 0 : ctx->cmac.c[2] ^= (u8)(alen >> (56 % (sizeof(alen) * 8)));
128 0 : ctx->cmac.c[3] ^= (u8)(alen >> (48 % (sizeof(alen) * 8)));
129 0 : ctx->cmac.c[4] ^= (u8)(alen >> (40 % (sizeof(alen) * 8)));
130 0 : ctx->cmac.c[5] ^= (u8)(alen >> (32 % (sizeof(alen) * 8)));
131 0 : ctx->cmac.c[6] ^= (u8)(alen >> 24);
132 0 : ctx->cmac.c[7] ^= (u8)(alen >> 16);
133 0 : ctx->cmac.c[8] ^= (u8)(alen >> 8);
134 0 : ctx->cmac.c[9] ^= (u8)alen;
135 : i = 10;
136 : } else {
137 0 : ctx->cmac.c[0] ^= 0xFF;
138 0 : ctx->cmac.c[1] ^= 0xFE;
139 0 : ctx->cmac.c[2] ^= (u8)(alen >> 24);
140 0 : ctx->cmac.c[3] ^= (u8)(alen >> 16);
141 0 : ctx->cmac.c[4] ^= (u8)(alen >> 8);
142 0 : ctx->cmac.c[5] ^= (u8)alen;
143 : i = 6;
144 : }
145 :
146 : do {
147 0 : for (; i < 16 && alen; ++i, ++aad, --alen)
148 0 : ctx->cmac.c[i] ^= *aad;
149 0 : (*block) (ctx->cmac.c, ctx->cmac.c, ctx->key), ctx->blocks++;
150 : i = 0;
151 0 : } 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 : */
160 : static void ctr64_inc(unsigned char *counter)
161 : {
162 : unsigned int n = 8;
163 : u8 c;
164 :
165 0 : counter += 8;
166 : do {
167 0 : --n;
168 0 : c = counter[n];
169 0 : ++c;
170 0 : counter[n] = c;
171 0 : if (c)
172 : return;
173 0 : } while (n);
174 : }
175 :
176 0 : int 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 0 : unsigned char flags0 = ctx->nonce.c[0];
183 0 : block128_f block = ctx->block;
184 0 : void *key = ctx->key;
185 : union {
186 : u64 u[2];
187 : u8 c[16];
188 : } scratch;
189 :
190 0 : if (!(flags0 & 0x40))
191 0 : (*block) (ctx->nonce.c, ctx->cmac.c, key), ctx->blocks++;
192 :
193 0 : ctx->nonce.c[0] = L = flags0 & 7;
194 0 : for (n = 0, i = 15 - L; i < 15; ++i) {
195 0 : n |= ctx->nonce.c[i];
196 0 : ctx->nonce.c[i] = 0;
197 0 : n <<= 8;
198 : }
199 0 : n |= ctx->nonce.c[15]; /* reconstructed length */
200 0 : ctx->nonce.c[15] = 1;
201 :
202 0 : if (n != len)
203 : return -1; /* length mismatch */
204 :
205 0 : ctx->blocks += ((len + 15) >> 3) | 1;
206 0 : if (ctx->blocks > (U64(1) << 61))
207 : return -2; /* too much data */
208 :
209 0 : 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 0 : ctx->cmac.u[0] ^= ((u64 *)inp)[0];
221 0 : ctx->cmac.u[1] ^= ((u64 *)inp)[1];
222 : #endif
223 0 : (*block) (ctx->cmac.c, ctx->cmac.c, key);
224 0 : (*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 0 : ((u64 *)out)[0] = scratch.u[0] ^ ((u64 *)inp)[0];
232 0 : ((u64 *)out)[1] = scratch.u[1] ^ ((u64 *)inp)[1];
233 : #endif
234 0 : inp += 16;
235 0 : out += 16;
236 0 : len -= 16;
237 : }
238 :
239 0 : if (len) {
240 0 : for (i = 0; i < len; ++i)
241 0 : ctx->cmac.c[i] ^= inp[i];
242 0 : (*block) (ctx->cmac.c, ctx->cmac.c, key);
243 0 : (*block) (ctx->nonce.c, scratch.c, key);
244 0 : for (i = 0; i < len; ++i)
245 0 : out[i] = scratch.c[i] ^ inp[i];
246 : }
247 :
248 0 : for (i = 15 - L; i < 16; ++i)
249 0 : ctx->nonce.c[i] = 0;
250 :
251 0 : (*block) (ctx->nonce.c, scratch.c, key);
252 0 : ctx->cmac.u[0] ^= scratch.u[0];
253 0 : ctx->cmac.u[1] ^= scratch.u[1];
254 :
255 0 : ctx->nonce.c[0] = flags0;
256 :
257 0 : return 0;
258 : }
259 :
260 0 : int 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 0 : unsigned char flags0 = ctx->nonce.c[0];
267 0 : block128_f block = ctx->block;
268 0 : void *key = ctx->key;
269 : union {
270 : u64 u[2];
271 : u8 c[16];
272 : } scratch;
273 :
274 0 : if (!(flags0 & 0x40))
275 0 : (*block) (ctx->nonce.c, ctx->cmac.c, key);
276 :
277 0 : ctx->nonce.c[0] = L = flags0 & 7;
278 0 : for (n = 0, i = 15 - L; i < 15; ++i) {
279 0 : n |= ctx->nonce.c[i];
280 0 : ctx->nonce.c[i] = 0;
281 0 : n <<= 8;
282 : }
283 0 : n |= ctx->nonce.c[15]; /* reconstructed length */
284 0 : ctx->nonce.c[15] = 1;
285 :
286 0 : if (n != len)
287 : return -1;
288 :
289 0 : while (len >= 16) {
290 : #if defined(STRICT_ALIGNMENT)
291 : union {
292 : u64 u[2];
293 : u8 c[16];
294 : } temp;
295 : #endif
296 0 : (*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 0 : ctx->cmac.u[0] ^= (((u64 *)out)[0] = scratch.u[0] ^ ((u64 *)inp)[0]);
305 0 : ctx->cmac.u[1] ^= (((u64 *)out)[1] = scratch.u[1] ^ ((u64 *)inp)[1]);
306 : #endif
307 0 : (*block) (ctx->cmac.c, ctx->cmac.c, key);
308 :
309 0 : inp += 16;
310 0 : out += 16;
311 0 : len -= 16;
312 : }
313 :
314 0 : if (len) {
315 0 : (*block) (ctx->nonce.c, scratch.c, key);
316 0 : for (i = 0; i < len; ++i)
317 0 : ctx->cmac.c[i] ^= (out[i] = scratch.c[i] ^ inp[i]);
318 0 : (*block) (ctx->cmac.c, ctx->cmac.c, key);
319 : }
320 :
321 0 : for (i = 15 - L; i < 16; ++i)
322 0 : ctx->nonce.c[i] = 0;
323 :
324 0 : (*block) (ctx->nonce.c, scratch.c, key);
325 0 : ctx->cmac.u[0] ^= scratch.u[0];
326 0 : ctx->cmac.u[1] ^= scratch.u[1];
327 :
328 0 : ctx->nonce.c[0] = flags0;
329 :
330 0 : return 0;
331 : }
332 :
333 0 : static void ctr64_add(unsigned char *counter, size_t inc)
334 : {
335 : size_t n = 8, val = 0;
336 :
337 0 : counter += 8;
338 : do {
339 0 : --n;
340 0 : val += counter[n] + (inc & 0xff);
341 0 : counter[n] = (unsigned char)val;
342 0 : val >>= 8; /* carry bit */
343 0 : inc >>= 8;
344 0 : } while (n && (inc || val));
345 0 : }
346 :
347 0 : int 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 0 : unsigned char flags0 = ctx->nonce.c[0];
354 0 : block128_f block = ctx->block;
355 0 : void *key = ctx->key;
356 : union {
357 : u64 u[2];
358 : u8 c[16];
359 : } scratch;
360 :
361 0 : if (!(flags0 & 0x40))
362 0 : (*block) (ctx->nonce.c, ctx->cmac.c, key), ctx->blocks++;
363 :
364 0 : ctx->nonce.c[0] = L = flags0 & 7;
365 0 : for (n = 0, i = 15 - L; i < 15; ++i) {
366 0 : n |= ctx->nonce.c[i];
367 0 : ctx->nonce.c[i] = 0;
368 0 : n <<= 8;
369 : }
370 0 : n |= ctx->nonce.c[15]; /* reconstructed length */
371 0 : ctx->nonce.c[15] = 1;
372 :
373 0 : if (n != len)
374 : return -1; /* length mismatch */
375 :
376 0 : ctx->blocks += ((len + 15) >> 3) | 1;
377 0 : if (ctx->blocks > (U64(1) << 61))
378 : return -2; /* too much data */
379 :
380 0 : if ((n = len / 16)) {
381 0 : (*stream) (inp, out, n, key, ctx->nonce.c, ctx->cmac.c);
382 0 : n *= 16;
383 0 : inp += n;
384 0 : out += n;
385 0 : len -= n;
386 0 : if (len)
387 0 : ctr64_add(ctx->nonce.c, n / 16);
388 : }
389 :
390 0 : if (len) {
391 0 : for (i = 0; i < len; ++i)
392 0 : ctx->cmac.c[i] ^= inp[i];
393 0 : (*block) (ctx->cmac.c, ctx->cmac.c, key);
394 0 : (*block) (ctx->nonce.c, scratch.c, key);
395 0 : for (i = 0; i < len; ++i)
396 0 : out[i] = scratch.c[i] ^ inp[i];
397 : }
398 :
399 0 : for (i = 15 - L; i < 16; ++i)
400 0 : ctx->nonce.c[i] = 0;
401 :
402 0 : (*block) (ctx->nonce.c, scratch.c, key);
403 0 : ctx->cmac.u[0] ^= scratch.u[0];
404 0 : ctx->cmac.u[1] ^= scratch.u[1];
405 :
406 0 : ctx->nonce.c[0] = flags0;
407 :
408 0 : return 0;
409 : }
410 :
411 0 : int 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 0 : unsigned char flags0 = ctx->nonce.c[0];
418 0 : block128_f block = ctx->block;
419 0 : void *key = ctx->key;
420 : union {
421 : u64 u[2];
422 : u8 c[16];
423 : } scratch;
424 :
425 0 : if (!(flags0 & 0x40))
426 0 : (*block) (ctx->nonce.c, ctx->cmac.c, key);
427 :
428 0 : ctx->nonce.c[0] = L = flags0 & 7;
429 0 : for (n = 0, i = 15 - L; i < 15; ++i) {
430 0 : n |= ctx->nonce.c[i];
431 0 : ctx->nonce.c[i] = 0;
432 0 : n <<= 8;
433 : }
434 0 : n |= ctx->nonce.c[15]; /* reconstructed length */
435 0 : ctx->nonce.c[15] = 1;
436 :
437 0 : if (n != len)
438 : return -1;
439 :
440 0 : if ((n = len / 16)) {
441 0 : (*stream) (inp, out, n, key, ctx->nonce.c, ctx->cmac.c);
442 0 : n *= 16;
443 0 : inp += n;
444 0 : out += n;
445 0 : len -= n;
446 0 : if (len)
447 0 : ctr64_add(ctx->nonce.c, n / 16);
448 : }
449 :
450 0 : if (len) {
451 0 : (*block) (ctx->nonce.c, scratch.c, key);
452 0 : for (i = 0; i < len; ++i)
453 0 : ctx->cmac.c[i] ^= (out[i] = scratch.c[i] ^ inp[i]);
454 0 : (*block) (ctx->cmac.c, ctx->cmac.c, key);
455 : }
456 :
457 0 : for (i = 15 - L; i < 16; ++i)
458 0 : ctx->nonce.c[i] = 0;
459 :
460 0 : (*block) (ctx->nonce.c, scratch.c, key);
461 0 : ctx->cmac.u[0] ^= scratch.u[0];
462 0 : ctx->cmac.u[1] ^= scratch.u[1];
463 :
464 0 : ctx->nonce.c[0] = flags0;
465 :
466 0 : return 0;
467 : }
468 :
469 0 : size_t CRYPTO_ccm128_tag(CCM128_CONTEXT *ctx, unsigned char *tag, size_t len)
470 : {
471 0 : unsigned int M = (ctx->nonce.c[0] >> 3) & 7; /* the M parameter */
472 :
473 0 : M *= 2;
474 0 : M += 2;
475 0 : if (len < M)
476 : return 0;
477 0 : memcpy(tag, ctx->cmac.c, M);
478 0 : return M;
479 : }
|