]>
git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/modes/ccm128.c
2 * Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved.
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
11 #include <openssl/crypto.h>
12 #include "crypto/modes.h"
14 #ifndef STRICT_ALIGNMENT
16 typedef u64 u64_a1
__attribute((__aligned__(1)));
23 * First you setup M and L parameters and pass the key schedule. This is
24 * called once per session setup...
26 void CRYPTO_ccm128_init(CCM128_CONTEXT
*ctx
,
27 unsigned int M
, unsigned int L
, void *key
,
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;
37 /* !!! Following interfaces are to be called *once* per packet !!! */
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
)
43 unsigned int L
= ctx
->nonce
.c
[0] & 7; /* the L parameter */
46 return -1; /* nonce is too short */
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)));
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
;
61 ctx
->nonce
.c
[0] &= ~0x40; /* clear Adata flag */
62 memcpy(&ctx
->nonce
.c
[1], nonce
, 14 - L
);
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
)
72 block128_f block
= ctx
->block
;
77 ctx
->nonce
.c
[0] |= 0x40; /* set Adata flag */
78 (*block
) (ctx
->nonce
.c
, ctx
->cmac
.c
, ctx
->key
), ctx
->blocks
++;
80 if (alen
< (0x10000 - 0x100)) {
81 ctx
->cmac
.c
[0] ^= (u8
)(alen
>> 8);
82 ctx
->cmac
.c
[1] ^= (u8
)alen
;
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
;
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
;
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
++;
115 /* Finally you encrypt or decrypt the message */
118 * counter part of nonce may not be larger than L*8 bits, L is not larger
119 * than 8, therefore 64-bit counter...
121 static void ctr64_inc(unsigned char *counter
)
137 int CRYPTO_ccm128_encrypt(CCM128_CONTEXT
*ctx
,
138 const unsigned char *inp
, unsigned char *out
,
143 unsigned char flags0
= ctx
->nonce
.c
[0];
144 block128_f block
= ctx
->block
;
145 void *key
= ctx
->key
;
151 if (!(flags0
& 0x40))
152 (*block
) (ctx
->nonce
.c
, ctx
->cmac
.c
, key
), ctx
->blocks
++;
154 ctx
->nonce
.c
[0] = L
= flags0
& 7;
155 for (n
= 0, i
= 15 - L
; i
< 15; ++i
) {
156 n
|= ctx
->nonce
.c
[i
];
160 n
|= ctx
->nonce
.c
[15]; /* reconstructed length */
161 ctx
->nonce
.c
[15] = 1;
164 return -1; /* length mismatch */
166 ctx
->blocks
+= ((len
+ 15) >> 3) | 1;
167 if (ctx
->blocks
> (U64(1) << 61))
168 return -2; /* too much data */
171 #if defined(STRICT_ALIGNMENT)
177 memcpy(temp
.c
, inp
, 16);
178 ctx
->cmac
.u
[0] ^= temp
.u
[0];
179 ctx
->cmac
.u
[1] ^= temp
.u
[1];
181 ctx
->cmac
.u
[0] ^= ((u64_a1
*)inp
)[0];
182 ctx
->cmac
.u
[1] ^= ((u64_a1
*)inp
)[1];
184 (*block
) (ctx
->cmac
.c
, ctx
->cmac
.c
, key
);
185 (*block
) (ctx
->nonce
.c
, scratch
.c
, key
);
186 ctr64_inc(ctx
->nonce
.c
);
187 #if defined(STRICT_ALIGNMENT)
188 temp
.u
[0] ^= scratch
.u
[0];
189 temp
.u
[1] ^= scratch
.u
[1];
190 memcpy(out
, temp
.c
, 16);
192 ((u64_a1
*)out
)[0] = scratch
.u
[0] ^ ((u64_a1
*)inp
)[0];
193 ((u64_a1
*)out
)[1] = scratch
.u
[1] ^ ((u64_a1
*)inp
)[1];
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
];
209 for (i
= 15 - L
; i
< 16; ++i
)
212 (*block
) (ctx
->nonce
.c
, scratch
.c
, key
);
213 ctx
->cmac
.u
[0] ^= scratch
.u
[0];
214 ctx
->cmac
.u
[1] ^= scratch
.u
[1];
216 ctx
->nonce
.c
[0] = flags0
;
221 int CRYPTO_ccm128_decrypt(CCM128_CONTEXT
*ctx
,
222 const unsigned char *inp
, unsigned char *out
,
227 unsigned char flags0
= ctx
->nonce
.c
[0];
228 block128_f block
= ctx
->block
;
229 void *key
= ctx
->key
;
235 if (!(flags0
& 0x40))
236 (*block
) (ctx
->nonce
.c
, ctx
->cmac
.c
, key
);
238 ctx
->nonce
.c
[0] = L
= flags0
& 7;
239 for (n
= 0, i
= 15 - L
; i
< 15; ++i
) {
240 n
|= ctx
->nonce
.c
[i
];
244 n
|= ctx
->nonce
.c
[15]; /* reconstructed length */
245 ctx
->nonce
.c
[15] = 1;
251 #if defined(STRICT_ALIGNMENT)
257 (*block
) (ctx
->nonce
.c
, scratch
.c
, key
);
258 ctr64_inc(ctx
->nonce
.c
);
259 #if defined(STRICT_ALIGNMENT)
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);
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]);
270 (*block
) (ctx
->cmac
.c
, ctx
->cmac
.c
, key
);
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
);
284 for (i
= 15 - L
; i
< 16; ++i
)
287 (*block
) (ctx
->nonce
.c
, scratch
.c
, key
);
288 ctx
->cmac
.u
[0] ^= scratch
.u
[0];
289 ctx
->cmac
.u
[1] ^= scratch
.u
[1];
291 ctx
->nonce
.c
[0] = flags0
;
296 static void ctr64_add(unsigned char *counter
, size_t inc
)
298 size_t n
= 8, val
= 0;
303 val
+= counter
[n
] + (inc
& 0xff);
304 counter
[n
] = (unsigned char)val
;
305 val
>>= 8; /* carry bit */
307 } while (n
&& (inc
|| val
));
310 int CRYPTO_ccm128_encrypt_ccm64(CCM128_CONTEXT
*ctx
,
311 const unsigned char *inp
, unsigned char *out
,
312 size_t len
, ccm128_f stream
)
316 unsigned char flags0
= ctx
->nonce
.c
[0];
317 block128_f block
= ctx
->block
;
318 void *key
= ctx
->key
;
324 if (!(flags0
& 0x40))
325 (*block
) (ctx
->nonce
.c
, ctx
->cmac
.c
, key
), ctx
->blocks
++;
327 ctx
->nonce
.c
[0] = L
= flags0
& 7;
328 for (n
= 0, i
= 15 - L
; i
< 15; ++i
) {
329 n
|= ctx
->nonce
.c
[i
];
333 n
|= ctx
->nonce
.c
[15]; /* reconstructed length */
334 ctx
->nonce
.c
[15] = 1;
337 return -1; /* length mismatch */
339 ctx
->blocks
+= ((len
+ 15) >> 3) | 1;
340 if (ctx
->blocks
> (U64(1) << 61))
341 return -2; /* too much data */
343 if ((n
= len
/ 16)) {
344 (*stream
) (inp
, out
, n
, key
, ctx
->nonce
.c
, ctx
->cmac
.c
);
350 ctr64_add(ctx
->nonce
.c
, n
/ 16);
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
];
362 for (i
= 15 - L
; i
< 16; ++i
)
365 (*block
) (ctx
->nonce
.c
, scratch
.c
, key
);
366 ctx
->cmac
.u
[0] ^= scratch
.u
[0];
367 ctx
->cmac
.u
[1] ^= scratch
.u
[1];
369 ctx
->nonce
.c
[0] = flags0
;
374 int CRYPTO_ccm128_decrypt_ccm64(CCM128_CONTEXT
*ctx
,
375 const unsigned char *inp
, unsigned char *out
,
376 size_t len
, ccm128_f stream
)
380 unsigned char flags0
= ctx
->nonce
.c
[0];
381 block128_f block
= ctx
->block
;
382 void *key
= ctx
->key
;
388 if (!(flags0
& 0x40))
389 (*block
) (ctx
->nonce
.c
, ctx
->cmac
.c
, key
);
391 ctx
->nonce
.c
[0] = L
= flags0
& 7;
392 for (n
= 0, i
= 15 - L
; i
< 15; ++i
) {
393 n
|= ctx
->nonce
.c
[i
];
397 n
|= ctx
->nonce
.c
[15]; /* reconstructed length */
398 ctx
->nonce
.c
[15] = 1;
403 if ((n
= len
/ 16)) {
404 (*stream
) (inp
, out
, n
, key
, ctx
->nonce
.c
, ctx
->cmac
.c
);
410 ctr64_add(ctx
->nonce
.c
, n
/ 16);
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
);
420 for (i
= 15 - L
; i
< 16; ++i
)
423 (*block
) (ctx
->nonce
.c
, scratch
.c
, key
);
424 ctx
->cmac
.u
[0] ^= scratch
.u
[0];
425 ctx
->cmac
.u
[1] ^= scratch
.u
[1];
427 ctx
->nonce
.c
[0] = flags0
;
432 size_t CRYPTO_ccm128_tag(CCM128_CONTEXT
*ctx
, unsigned char *tag
, size_t len
)
434 unsigned int M
= (ctx
->nonce
.c
[0] >> 3) & 7; /* the M parameter */
440 memcpy(tag
, ctx
->cmac
.c
, M
);