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