xref: /openbsd/lib/libcrypto/modes/ccm128.c (revision 0e3d1220)
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