]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/modes/ccm128.c
Update copyright year
[thirdparty/openssl.git] / crypto / modes / ccm128.c
CommitLineData
4f22f405 1/*
00c405b3 2 * Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved.
d3fad7cb 3 *
81cae8ce 4 * Licensed under the Apache License 2.0 (the "License"). You may not use
4f22f405
RS
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
d3fad7cb
AP
8 */
9
d3fad7cb 10#include <string.h>
459b15d4 11#include <openssl/crypto.h>
25f2138b 12#include "crypto/modes.h"
d3fad7cb 13
77286fe3
BE
14#ifndef STRICT_ALIGNMENT
15# ifdef __GNUC__
16typedef u64 u64_a1 __attribute((__aligned__(1)));
17# else
18typedef u64 u64_a1;
19# endif
20#endif
21
0f113f3e
MC
22/*
23 * First you setup M and L parameters and pass the key schedule. This is
24 * called once per session setup...
25 */
d3fad7cb 26void CRYPTO_ccm128_init(CCM128_CONTEXT *ctx,
0f113f3e
MC
27 unsigned int M, unsigned int L, void *key,
28 block128_f block)
d3fad7cb 29{
0f113f3e
MC
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;
d3fad7cb
AP
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 */
40int CRYPTO_ccm128_setiv(CCM128_CONTEXT *ctx,
0f113f3e 41 const unsigned char *nonce, size_t nlen, size_t mlen)
d3fad7cb 42{
0f113f3e 43 unsigned int L = ctx->nonce.c[0] & 7; /* the L parameter */
d3fad7cb 44
0f113f3e
MC
45 if (nlen < (14 - L))
46 return -1; /* nonce is too short */
d3fad7cb 47
0f113f3e
MC
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;
d3fad7cb 55
0f113f3e
MC
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;
d3fad7cb 60
0f113f3e
MC
61 ctx->nonce.c[0] &= ~0x40; /* clear Adata flag */
62 memcpy(&ctx->nonce.c[1], nonce, 14 - L);
d3fad7cb 63
0f113f3e 64 return 0;
d3fad7cb
AP
65}
66
67/* Then you pass additional authentication data, this is optional */
68void CRYPTO_ccm128_aad(CCM128_CONTEXT *ctx,
0f113f3e
MC
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);
d3fad7cb
AP
113}
114
115/* Finally you encrypt or decrypt the message */
116
0f113f3e
MC
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 */
121static 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);
d3fad7cb
AP
135}
136
137int CRYPTO_ccm128_encrypt(CCM128_CONTEXT *ctx,
0f113f3e
MC
138 const unsigned char *inp, unsigned char *out,
139 size_t len)
d3fad7cb 140{
0f113f3e
MC
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) {
d3fad7cb 171#if defined(STRICT_ALIGNMENT)
0f113f3e
MC
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];
d3fad7cb 180#else
77286fe3
BE
181 ctx->cmac.u[0] ^= ((u64_a1 *)inp)[0];
182 ctx->cmac.u[1] ^= ((u64_a1 *)inp)[1];
d3fad7cb 183#endif
0f113f3e
MC
184 (*block) (ctx->cmac.c, ctx->cmac.c, key);
185 (*block) (ctx->nonce.c, scratch.c, key);
186 ctr64_inc(ctx->nonce.c);
d3fad7cb 187#if defined(STRICT_ALIGNMENT)
0f113f3e
MC
188 temp.u[0] ^= scratch.u[0];
189 temp.u[1] ^= scratch.u[1];
190 memcpy(out, temp.c, 16);
d3fad7cb 191#else
77286fe3
BE
192 ((u64_a1 *)out)[0] = scratch.u[0] ^ ((u64_a1 *)inp)[0];
193 ((u64_a1 *)out)[1] = scratch.u[1] ^ ((u64_a1 *)inp)[1];
d3fad7cb 194#endif
0f113f3e
MC
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;
d3fad7cb
AP
219}
220
221int CRYPTO_ccm128_decrypt(CCM128_CONTEXT *ctx,
0f113f3e
MC
222 const unsigned char *inp, unsigned char *out,
223 size_t len)
d3fad7cb 224{
0f113f3e
MC
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) {
5f1b10ed 251#if defined(STRICT_ALIGNMENT)
0f113f3e
MC
252 union {
253 u64 u[2];
254 u8 c[16];
255 } temp;
5f1b10ed 256#endif
0f113f3e
MC
257 (*block) (ctx->nonce.c, scratch.c, key);
258 ctr64_inc(ctx->nonce.c);
d3fad7cb 259#if defined(STRICT_ALIGNMENT)
0f113f3e
MC
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);
d3fad7cb 264#else
77286fe3
BE
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]);
d3fad7cb 269#endif
0f113f3e 270 (*block) (ctx->cmac.c, ctx->cmac.c, key);
d3fad7cb 271
0f113f3e
MC
272 inp += 16;
273 out += 16;
274 len -= 16;
275 }
d3fad7cb 276
0f113f3e
MC
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 }
d3fad7cb 283
0f113f3e
MC
284 for (i = 15 - L; i < 16; ++i)
285 ctx->nonce.c[i] = 0;
d3fad7cb 286
0f113f3e
MC
287 (*block) (ctx->nonce.c, scratch.c, key);
288 ctx->cmac.u[0] ^= scratch.u[0];
289 ctx->cmac.u[1] ^= scratch.u[1];
f855b9d7 290
0f113f3e 291 ctx->nonce.c[0] = flags0;
f855b9d7 292
0f113f3e 293 return 0;
f855b9d7
AP
294}
295
0f113f3e
MC
296static 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));
f855b9d7
AP
308}
309
310int CRYPTO_ccm128_encrypt_ccm64(CCM128_CONTEXT *ctx,
0f113f3e
MC
311 const unsigned char *inp, unsigned char *out,
312 size_t len, ccm128_f stream)
f855b9d7 313{
0f113f3e
MC
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;
f855b9d7
AP
372}
373
374int CRYPTO_ccm128_decrypt_ccm64(CCM128_CONTEXT *ctx,
0f113f3e
MC
375 const unsigned char *inp, unsigned char *out,
376 size_t len, ccm128_f stream)
f855b9d7 377{
0f113f3e
MC
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;
d3fad7cb
AP
430}
431
0f113f3e
MC
432size_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;
514c9da4 438 if (len != M)
0f113f3e
MC
439 return 0;
440 memcpy(tag, ctx->cmac.c, M);
441 return M;
d3fad7cb 442}