/src/openssl30/crypto/modes/ccm128.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2011-2020 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 | 557 | { |
30 | 557 | memset(ctx->nonce.c, 0, sizeof(ctx->nonce.c)); |
31 | 557 | ctx->nonce.c[0] = ((u8)(L - 1) & 7) | (u8)(((M - 2) / 2) & 7) << 3; |
32 | 557 | ctx->blocks = 0; |
33 | 557 | ctx->block = block; |
34 | 557 | ctx->key = key; |
35 | 557 | } |
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 | 14.4k | { |
43 | 14.4k | unsigned int L = ctx->nonce.c[0] & 7; /* the L parameter */ |
44 | | |
45 | 14.4k | if (nlen < (14 - L)) |
46 | 0 | return -1; /* nonce is too short */ |
47 | | |
48 | 14.4k | if (sizeof(mlen) == 8 && L >= 3) { |
49 | 0 | ctx->nonce.c[8] = (u8)(mlen >> (56 % (sizeof(mlen) * 8))); |
50 | 0 | ctx->nonce.c[9] = (u8)(mlen >> (48 % (sizeof(mlen) * 8))); |
51 | 0 | ctx->nonce.c[10] = (u8)(mlen >> (40 % (sizeof(mlen) * 8))); |
52 | 0 | ctx->nonce.c[11] = (u8)(mlen >> (32 % (sizeof(mlen) * 8))); |
53 | 0 | } else |
54 | 14.4k | ctx->nonce.u[1] = 0; |
55 | | |
56 | 14.4k | ctx->nonce.c[12] = (u8)(mlen >> 24); |
57 | 14.4k | ctx->nonce.c[13] = (u8)(mlen >> 16); |
58 | 14.4k | ctx->nonce.c[14] = (u8)(mlen >> 8); |
59 | 14.4k | ctx->nonce.c[15] = (u8)mlen; |
60 | | |
61 | 14.4k | ctx->nonce.c[0] &= ~0x40; /* clear Adata flag */ |
62 | 14.4k | memcpy(&ctx->nonce.c[1], nonce, 14 - L); |
63 | | |
64 | 14.4k | return 0; |
65 | 14.4k | } |
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 | 14.4k | { |
71 | 14.4k | unsigned int i; |
72 | 14.4k | block128_f block = ctx->block; |
73 | | |
74 | 14.4k | if (alen == 0) |
75 | 0 | return; |
76 | | |
77 | 14.4k | ctx->nonce.c[0] |= 0x40; /* set Adata flag */ |
78 | 14.4k | (*block) (ctx->nonce.c, ctx->cmac.c, ctx->key), ctx->blocks++; |
79 | | |
80 | 14.4k | if (alen < (0x10000 - 0x100)) { |
81 | 14.4k | ctx->cmac.c[0] ^= (u8)(alen >> 8); |
82 | 14.4k | ctx->cmac.c[1] ^= (u8)alen; |
83 | 14.4k | i = 2; |
84 | 14.4k | } else if (sizeof(alen) == 8 |
85 | 0 | && alen >= (size_t)1 << (32 % (sizeof(alen) * 8))) { |
86 | 0 | ctx->cmac.c[0] ^= 0xFF; |
87 | 0 | ctx->cmac.c[1] ^= 0xFF; |
88 | 0 | ctx->cmac.c[2] ^= (u8)(alen >> (56 % (sizeof(alen) * 8))); |
89 | 0 | ctx->cmac.c[3] ^= (u8)(alen >> (48 % (sizeof(alen) * 8))); |
90 | 0 | ctx->cmac.c[4] ^= (u8)(alen >> (40 % (sizeof(alen) * 8))); |
91 | 0 | ctx->cmac.c[5] ^= (u8)(alen >> (32 % (sizeof(alen) * 8))); |
92 | 0 | ctx->cmac.c[6] ^= (u8)(alen >> 24); |
93 | 0 | ctx->cmac.c[7] ^= (u8)(alen >> 16); |
94 | 0 | ctx->cmac.c[8] ^= (u8)(alen >> 8); |
95 | 0 | ctx->cmac.c[9] ^= (u8)alen; |
96 | 0 | i = 10; |
97 | 0 | } else { |
98 | 0 | ctx->cmac.c[0] ^= 0xFF; |
99 | 0 | ctx->cmac.c[1] ^= 0xFE; |
100 | 0 | ctx->cmac.c[2] ^= (u8)(alen >> 24); |
101 | 0 | ctx->cmac.c[3] ^= (u8)(alen >> 16); |
102 | 0 | ctx->cmac.c[4] ^= (u8)(alen >> 8); |
103 | 0 | ctx->cmac.c[5] ^= (u8)alen; |
104 | 0 | i = 6; |
105 | 0 | } |
106 | | |
107 | 14.4k | do { |
108 | 202k | for (; i < 16 && alen; ++i, ++aad, --alen) |
109 | 188k | ctx->cmac.c[i] ^= *aad; |
110 | 14.4k | (*block) (ctx->cmac.c, ctx->cmac.c, ctx->key), ctx->blocks++; |
111 | 14.4k | i = 0; |
112 | 14.4k | } while (alen); |
113 | 14.4k | } |
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 | 0 | { |
123 | 0 | unsigned int n = 8; |
124 | 0 | u8 c; |
125 | |
|
126 | 0 | counter += 8; |
127 | 0 | do { |
128 | 0 | --n; |
129 | 0 | c = counter[n]; |
130 | 0 | ++c; |
131 | 0 | counter[n] = c; |
132 | 0 | if (c) |
133 | 0 | return; |
134 | 0 | } while (n); |
135 | 0 | } |
136 | | |
137 | | int CRYPTO_ccm128_encrypt(CCM128_CONTEXT *ctx, |
138 | | const unsigned char *inp, unsigned char *out, |
139 | | size_t len) |
140 | 0 | { |
141 | 0 | size_t n; |
142 | 0 | unsigned int i, L; |
143 | 0 | unsigned char flags0 = ctx->nonce.c[0]; |
144 | 0 | block128_f block = ctx->block; |
145 | 0 | void *key = ctx->key; |
146 | 0 | union { |
147 | 0 | u64 u[2]; |
148 | 0 | u8 c[16]; |
149 | 0 | } scratch; |
150 | |
|
151 | 0 | if (!(flags0 & 0x40)) |
152 | 0 | (*block) (ctx->nonce.c, ctx->cmac.c, key), ctx->blocks++; |
153 | |
|
154 | 0 | ctx->nonce.c[0] = L = flags0 & 7; |
155 | 0 | for (n = 0, i = 15 - L; i < 15; ++i) { |
156 | 0 | n |= ctx->nonce.c[i]; |
157 | 0 | ctx->nonce.c[i] = 0; |
158 | 0 | n <<= 8; |
159 | 0 | } |
160 | 0 | n |= ctx->nonce.c[15]; /* reconstructed length */ |
161 | 0 | ctx->nonce.c[15] = 1; |
162 | |
|
163 | 0 | if (n != len) |
164 | 0 | return -1; /* length mismatch */ |
165 | | |
166 | 0 | ctx->blocks += ((len + 15) >> 3) | 1; |
167 | 0 | if (ctx->blocks > (U64(1) << 61)) |
168 | 0 | return -2; /* too much data */ |
169 | | |
170 | 0 | while (len >= 16) { |
171 | 0 | #if defined(STRICT_ALIGNMENT) |
172 | 0 | union { |
173 | 0 | u64 u[2]; |
174 | 0 | u8 c[16]; |
175 | 0 | } temp; |
176 | |
|
177 | 0 | memcpy(temp.c, inp, 16); |
178 | 0 | ctx->cmac.u[0] ^= temp.u[0]; |
179 | 0 | 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 | 0 | (*block) (ctx->cmac.c, ctx->cmac.c, key); |
185 | 0 | (*block) (ctx->nonce.c, scratch.c, key); |
186 | 0 | ctr64_inc(ctx->nonce.c); |
187 | 0 | #if defined(STRICT_ALIGNMENT) |
188 | 0 | temp.u[0] ^= scratch.u[0]; |
189 | 0 | temp.u[1] ^= scratch.u[1]; |
190 | 0 | 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 | 0 | inp += 16; |
196 | 0 | out += 16; |
197 | 0 | len -= 16; |
198 | 0 | } |
199 | |
|
200 | 0 | if (len) { |
201 | 0 | for (i = 0; i < len; ++i) |
202 | 0 | ctx->cmac.c[i] ^= inp[i]; |
203 | 0 | (*block) (ctx->cmac.c, ctx->cmac.c, key); |
204 | 0 | (*block) (ctx->nonce.c, scratch.c, key); |
205 | 0 | for (i = 0; i < len; ++i) |
206 | 0 | out[i] = scratch.c[i] ^ inp[i]; |
207 | 0 | } |
208 | |
|
209 | 0 | for (i = 15 - L; i < 16; ++i) |
210 | 0 | ctx->nonce.c[i] = 0; |
211 | |
|
212 | 0 | (*block) (ctx->nonce.c, scratch.c, key); |
213 | 0 | ctx->cmac.u[0] ^= scratch.u[0]; |
214 | 0 | ctx->cmac.u[1] ^= scratch.u[1]; |
215 | |
|
216 | 0 | ctx->nonce.c[0] = flags0; |
217 | |
|
218 | 0 | return 0; |
219 | 0 | } |
220 | | |
221 | | int CRYPTO_ccm128_decrypt(CCM128_CONTEXT *ctx, |
222 | | const unsigned char *inp, unsigned char *out, |
223 | | size_t len) |
224 | 0 | { |
225 | 0 | size_t n; |
226 | 0 | unsigned int i, L; |
227 | 0 | unsigned char flags0 = ctx->nonce.c[0]; |
228 | 0 | block128_f block = ctx->block; |
229 | 0 | void *key = ctx->key; |
230 | 0 | union { |
231 | 0 | u64 u[2]; |
232 | 0 | u8 c[16]; |
233 | 0 | } scratch; |
234 | |
|
235 | 0 | if (!(flags0 & 0x40)) |
236 | 0 | (*block) (ctx->nonce.c, ctx->cmac.c, key); |
237 | |
|
238 | 0 | ctx->nonce.c[0] = L = flags0 & 7; |
239 | 0 | for (n = 0, i = 15 - L; i < 15; ++i) { |
240 | 0 | n |= ctx->nonce.c[i]; |
241 | 0 | ctx->nonce.c[i] = 0; |
242 | 0 | n <<= 8; |
243 | 0 | } |
244 | 0 | n |= ctx->nonce.c[15]; /* reconstructed length */ |
245 | 0 | ctx->nonce.c[15] = 1; |
246 | |
|
247 | 0 | if (n != len) |
248 | 0 | return -1; |
249 | | |
250 | 0 | while (len >= 16) { |
251 | 0 | #if defined(STRICT_ALIGNMENT) |
252 | 0 | union { |
253 | 0 | u64 u[2]; |
254 | 0 | u8 c[16]; |
255 | 0 | } temp; |
256 | 0 | #endif |
257 | 0 | (*block) (ctx->nonce.c, scratch.c, key); |
258 | 0 | ctr64_inc(ctx->nonce.c); |
259 | 0 | #if defined(STRICT_ALIGNMENT) |
260 | 0 | memcpy(temp.c, inp, 16); |
261 | 0 | ctx->cmac.u[0] ^= (scratch.u[0] ^= temp.u[0]); |
262 | 0 | ctx->cmac.u[1] ^= (scratch.u[1] ^= temp.u[1]); |
263 | 0 | 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 | 0 | (*block) (ctx->cmac.c, ctx->cmac.c, key); |
271 | |
|
272 | 0 | inp += 16; |
273 | 0 | out += 16; |
274 | 0 | len -= 16; |
275 | 0 | } |
276 | |
|
277 | 0 | if (len) { |
278 | 0 | (*block) (ctx->nonce.c, scratch.c, key); |
279 | 0 | for (i = 0; i < len; ++i) |
280 | 0 | ctx->cmac.c[i] ^= (out[i] = scratch.c[i] ^ inp[i]); |
281 | 0 | (*block) (ctx->cmac.c, ctx->cmac.c, key); |
282 | 0 | } |
283 | |
|
284 | 0 | for (i = 15 - L; i < 16; ++i) |
285 | 0 | ctx->nonce.c[i] = 0; |
286 | |
|
287 | 0 | (*block) (ctx->nonce.c, scratch.c, key); |
288 | 0 | ctx->cmac.u[0] ^= scratch.u[0]; |
289 | 0 | ctx->cmac.u[1] ^= scratch.u[1]; |
290 | |
|
291 | 0 | ctx->nonce.c[0] = flags0; |
292 | |
|
293 | 0 | return 0; |
294 | 0 | } |
295 | | |
296 | | static void ctr64_add(unsigned char *counter, size_t inc) |
297 | 812 | { |
298 | 812 | size_t n = 8, val = 0; |
299 | | |
300 | 812 | counter += 8; |
301 | 1.27k | do { |
302 | 1.27k | --n; |
303 | 1.27k | val += counter[n] + (inc & 0xff); |
304 | 1.27k | counter[n] = (unsigned char)val; |
305 | 1.27k | val >>= 8; /* carry bit */ |
306 | 1.27k | inc >>= 8; |
307 | 1.27k | } while (n && (inc || val)); |
308 | 812 | } |
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 | 262 | { |
314 | 262 | size_t n; |
315 | 262 | unsigned int i, L; |
316 | 262 | unsigned char flags0 = ctx->nonce.c[0]; |
317 | 262 | block128_f block = ctx->block; |
318 | 262 | void *key = ctx->key; |
319 | 262 | union { |
320 | 262 | u64 u[2]; |
321 | 262 | u8 c[16]; |
322 | 262 | } scratch; |
323 | | |
324 | 262 | if (!(flags0 & 0x40)) |
325 | 0 | (*block) (ctx->nonce.c, ctx->cmac.c, key), ctx->blocks++; |
326 | | |
327 | 262 | ctx->nonce.c[0] = L = flags0 & 7; |
328 | 786 | for (n = 0, i = 15 - L; i < 15; ++i) { |
329 | 524 | n |= ctx->nonce.c[i]; |
330 | 524 | ctx->nonce.c[i] = 0; |
331 | 524 | n <<= 8; |
332 | 524 | } |
333 | 262 | n |= ctx->nonce.c[15]; /* reconstructed length */ |
334 | 262 | ctx->nonce.c[15] = 1; |
335 | | |
336 | 262 | if (n != len) |
337 | 0 | return -1; /* length mismatch */ |
338 | | |
339 | 262 | ctx->blocks += ((len + 15) >> 3) | 1; |
340 | 262 | if (ctx->blocks > (U64(1) << 61)) |
341 | 0 | return -2; /* too much data */ |
342 | | |
343 | 262 | if ((n = len / 16)) { |
344 | 143 | (*stream) (inp, out, n, key, ctx->nonce.c, ctx->cmac.c); |
345 | 143 | n *= 16; |
346 | 143 | inp += n; |
347 | 143 | out += n; |
348 | 143 | len -= n; |
349 | 143 | if (len) |
350 | 0 | ctr64_add(ctx->nonce.c, n / 16); |
351 | 143 | } |
352 | | |
353 | 262 | if (len) { |
354 | 357 | for (i = 0; i < len; ++i) |
355 | 238 | ctx->cmac.c[i] ^= inp[i]; |
356 | 119 | (*block) (ctx->cmac.c, ctx->cmac.c, key); |
357 | 119 | (*block) (ctx->nonce.c, scratch.c, key); |
358 | 357 | for (i = 0; i < len; ++i) |
359 | 238 | out[i] = scratch.c[i] ^ inp[i]; |
360 | 119 | } |
361 | | |
362 | 1.04k | for (i = 15 - L; i < 16; ++i) |
363 | 786 | ctx->nonce.c[i] = 0; |
364 | | |
365 | 262 | (*block) (ctx->nonce.c, scratch.c, key); |
366 | 262 | ctx->cmac.u[0] ^= scratch.u[0]; |
367 | 262 | ctx->cmac.u[1] ^= scratch.u[1]; |
368 | | |
369 | 262 | ctx->nonce.c[0] = flags0; |
370 | | |
371 | 262 | return 0; |
372 | 262 | } |
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 | 14.2k | { |
378 | 14.2k | size_t n; |
379 | 14.2k | unsigned int i, L; |
380 | 14.2k | unsigned char flags0 = ctx->nonce.c[0]; |
381 | 14.2k | block128_f block = ctx->block; |
382 | 14.2k | void *key = ctx->key; |
383 | 14.2k | union { |
384 | 14.2k | u64 u[2]; |
385 | 14.2k | u8 c[16]; |
386 | 14.2k | } scratch; |
387 | | |
388 | 14.2k | if (!(flags0 & 0x40)) |
389 | 0 | (*block) (ctx->nonce.c, ctx->cmac.c, key); |
390 | | |
391 | 14.2k | ctx->nonce.c[0] = L = flags0 & 7; |
392 | 42.6k | for (n = 0, i = 15 - L; i < 15; ++i) { |
393 | 28.4k | n |= ctx->nonce.c[i]; |
394 | 28.4k | ctx->nonce.c[i] = 0; |
395 | 28.4k | n <<= 8; |
396 | 28.4k | } |
397 | 14.2k | n |= ctx->nonce.c[15]; /* reconstructed length */ |
398 | 14.2k | ctx->nonce.c[15] = 1; |
399 | | |
400 | 14.2k | if (n != len) |
401 | 0 | return -1; |
402 | | |
403 | 14.2k | if ((n = len / 16)) { |
404 | 1.08k | (*stream) (inp, out, n, key, ctx->nonce.c, ctx->cmac.c); |
405 | 1.08k | n *= 16; |
406 | 1.08k | inp += n; |
407 | 1.08k | out += n; |
408 | 1.08k | len -= n; |
409 | 1.08k | if (len) |
410 | 812 | ctr64_add(ctx->nonce.c, n / 16); |
411 | 1.08k | } |
412 | | |
413 | 14.2k | if (len) { |
414 | 1.11k | (*block) (ctx->nonce.c, scratch.c, key); |
415 | 11.0k | for (i = 0; i < len; ++i) |
416 | 9.90k | ctx->cmac.c[i] ^= (out[i] = scratch.c[i] ^ inp[i]); |
417 | 1.11k | (*block) (ctx->cmac.c, ctx->cmac.c, key); |
418 | 1.11k | } |
419 | | |
420 | 56.8k | for (i = 15 - L; i < 16; ++i) |
421 | 42.6k | ctx->nonce.c[i] = 0; |
422 | | |
423 | 14.2k | (*block) (ctx->nonce.c, scratch.c, key); |
424 | 14.2k | ctx->cmac.u[0] ^= scratch.u[0]; |
425 | 14.2k | ctx->cmac.u[1] ^= scratch.u[1]; |
426 | | |
427 | 14.2k | ctx->nonce.c[0] = flags0; |
428 | | |
429 | 14.2k | return 0; |
430 | 14.2k | } |
431 | | |
432 | | size_t CRYPTO_ccm128_tag(CCM128_CONTEXT *ctx, unsigned char *tag, size_t len) |
433 | 14.4k | { |
434 | 14.4k | unsigned int M = (ctx->nonce.c[0] >> 3) & 7; /* the M parameter */ |
435 | | |
436 | 14.4k | M *= 2; |
437 | 14.4k | M += 2; |
438 | 14.4k | if (len != M) |
439 | 0 | return 0; |
440 | 14.4k | memcpy(tag, ctx->cmac.c, M); |
441 | 14.4k | return M; |
442 | 14.4k | } |