Merge pull request #2747 from Eltrick/stylise-dormakaba
[RRG-proxmark3.git] / common / mbedtls / ccm.c
blob789446f46668c0a98518e25494204868026c54cf
1 /*
2 * NIST SP800-38C compliant CCM implementation
4 * Copyright The Mbed TLS Contributors
5 * SPDX-License-Identifier: Apache-2.0
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 * Definition of CCM:
22 * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
23 * RFC 3610 "Counter with CBC-MAC (CCM)"
25 * Related:
26 * RFC 5116 "An Interface and Algorithms for Authenticated Encryption"
29 #include "common.h"
31 #if defined(MBEDTLS_CCM_C)
33 #include "mbedtls/ccm.h"
34 #include "mbedtls/platform_util.h"
35 #include "mbedtls/error.h"
37 #include <string.h>
39 #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
40 #if defined(MBEDTLS_PLATFORM_C)
41 #include "mbedtls/platform.h"
42 #else
43 #include <stdio.h>
44 #define mbedtls_printf printf
45 #endif /* MBEDTLS_PLATFORM_C */
46 #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
48 #if !defined(MBEDTLS_CCM_ALT)
50 #define CCM_VALIDATE_RET( cond ) \
51 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CCM_BAD_INPUT )
52 #define CCM_VALIDATE( cond ) \
53 MBEDTLS_INTERNAL_VALIDATE( cond )
55 #define CCM_ENCRYPT 0
56 #define CCM_DECRYPT 1
59 * Initialize context
61 void mbedtls_ccm_init(mbedtls_ccm_context *ctx) {
62 CCM_VALIDATE(ctx != NULL);
63 memset(ctx, 0, sizeof(mbedtls_ccm_context));
66 int mbedtls_ccm_setkey(mbedtls_ccm_context *ctx,
67 mbedtls_cipher_id_t cipher,
68 const unsigned char *key,
69 unsigned int keybits) {
70 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
71 const mbedtls_cipher_info_t *cipher_info;
73 CCM_VALIDATE_RET(ctx != NULL);
74 CCM_VALIDATE_RET(key != NULL);
76 cipher_info = mbedtls_cipher_info_from_values(cipher, keybits,
77 MBEDTLS_MODE_ECB);
78 if (cipher_info == NULL)
79 return (MBEDTLS_ERR_CCM_BAD_INPUT);
81 if (cipher_info->block_size != 16)
82 return (MBEDTLS_ERR_CCM_BAD_INPUT);
84 mbedtls_cipher_free(&ctx->cipher_ctx);
86 if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0)
87 return (ret);
89 if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
90 MBEDTLS_ENCRYPT)) != 0) {
91 return (ret);
94 return (0);
98 * Free context
100 void mbedtls_ccm_free(mbedtls_ccm_context *ctx) {
101 if (ctx == NULL)
102 return;
103 mbedtls_cipher_free(&ctx->cipher_ctx);
104 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ccm_context));
108 * Macros for common operations.
109 * Results in smaller compiled code than static inline functions.
113 * Update the CBC-MAC state in y using a block in b
114 * (Always using b as the source helps the compiler optimise a bit better.)
116 #define UPDATE_CBC_MAC \
117 for( i = 0; i < 16; i++ ) \
118 y[i] ^= b[i]; \
120 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, y, 16, y, &olen ) ) != 0 ) \
121 return( ret );
124 * Encrypt or decrypt a partial block with CTR
125 * Warning: using b for temporary storage! src and dst must not be b!
126 * This avoids allocating one more 16 bytes buffer while allowing src == dst.
128 #define CTR_CRYPT( dst, src, len ) \
129 do \
131 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctr, \
132 16, b, &olen ) ) != 0 ) \
134 return( ret ); \
137 for( i = 0; i < (len); i++ ) \
138 (dst)[i] = (src)[i] ^ b[i]; \
139 } while( 0 )
142 * Authenticated encryption or decryption
144 static int ccm_auth_crypt(mbedtls_ccm_context *ctx, int mode, size_t length,
145 const unsigned char *iv, size_t iv_len,
146 const unsigned char *add, size_t add_len,
147 const unsigned char *input, unsigned char *output,
148 unsigned char *tag, size_t tag_len) {
149 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
150 unsigned char i;
151 unsigned char q;
152 size_t len_left, olen;
153 unsigned char b[16];
154 unsigned char y[16];
155 unsigned char ctr[16];
156 const unsigned char *src;
157 unsigned char *dst;
160 * Check length requirements: SP800-38C A.1
161 * Additional requirement: a < 2^16 - 2^8 to simplify the code.
162 * 'length' checked later (when writing it to the first block)
164 * Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4).
166 if (tag_len == 2 || tag_len > 16 || tag_len % 2 != 0)
167 return (MBEDTLS_ERR_CCM_BAD_INPUT);
169 /* Also implies q is within bounds */
170 if (iv_len < 7 || iv_len > 13)
171 return (MBEDTLS_ERR_CCM_BAD_INPUT);
173 if (add_len >= 0xFF00)
174 return (MBEDTLS_ERR_CCM_BAD_INPUT);
176 q = 16 - 1 - (unsigned char) iv_len;
179 * First block B_0:
180 * 0 .. 0 flags
181 * 1 .. iv_len nonce (aka iv)
182 * iv_len+1 .. 15 length
184 * With flags as (bits):
185 * 7 0
186 * 6 add present?
187 * 5 .. 3 (t - 2) / 2
188 * 2 .. 0 q - 1
190 b[0] = 0;
191 b[0] |= (add_len > 0) << 6;
192 b[0] |= ((tag_len - 2) / 2) << 3;
193 b[0] |= q - 1;
195 memcpy(b + 1, iv, iv_len);
197 for (i = 0, len_left = length; i < q; i++, len_left >>= 8)
198 b[15 - i] = (unsigned char)(len_left & 0xFF);
200 if (len_left > 0)
201 return (MBEDTLS_ERR_CCM_BAD_INPUT);
204 /* Start CBC-MAC with first block */
205 memset(y, 0, 16);
206 UPDATE_CBC_MAC;
209 * If there is additional data, update CBC-MAC with
210 * add_len, add, 0 (padding to a block boundary)
212 if (add_len > 0) {
213 size_t use_len;
214 len_left = add_len;
215 src = add;
217 memset(b, 0, 16);
218 b[0] = (unsigned char)((add_len >> 8) & 0xFF);
219 b[1] = (unsigned char)((add_len) & 0xFF);
221 use_len = len_left < 16 - 2 ? len_left : 16 - 2;
222 memcpy(b + 2, src, use_len);
223 len_left -= use_len;
224 src += use_len;
226 UPDATE_CBC_MAC;
228 while (len_left > 0) {
229 use_len = len_left > 16 ? 16 : len_left;
231 memset(b, 0, 16);
232 memcpy(b, src, use_len);
233 UPDATE_CBC_MAC;
235 len_left -= use_len;
236 src += use_len;
241 * Prepare counter block for encryption:
242 * 0 .. 0 flags
243 * 1 .. iv_len nonce (aka iv)
244 * iv_len+1 .. 15 counter (initially 1)
246 * With flags as (bits):
247 * 7 .. 3 0
248 * 2 .. 0 q - 1
250 ctr[0] = q - 1;
251 memcpy(ctr + 1, iv, iv_len);
252 memset(ctr + 1 + iv_len, 0, q);
253 ctr[15] = 1;
256 * Authenticate and {en,de}crypt the message.
258 * The only difference between encryption and decryption is
259 * the respective order of authentication and {en,de}cryption.
261 len_left = length;
262 src = input;
263 dst = output;
265 while (len_left > 0) {
266 size_t use_len = len_left > 16 ? 16 : len_left;
268 if (mode == CCM_ENCRYPT) {
269 memset(b, 0, 16);
270 memcpy(b, src, use_len);
271 UPDATE_CBC_MAC;
274 CTR_CRYPT(dst, src, use_len);
276 if (mode == CCM_DECRYPT) {
277 memset(b, 0, 16);
278 memcpy(b, dst, use_len);
279 UPDATE_CBC_MAC;
282 dst += use_len;
283 src += use_len;
284 len_left -= use_len;
287 * Increment counter.
288 * No need to check for overflow thanks to the length check above.
290 for (i = 0; i < q; i++)
291 if (++ctr[15 - i] != 0)
292 break;
296 * Authentication: reset counter and crypt/mask internal tag
298 for (i = 0; i < q; i++)
299 ctr[15 - i] = 0;
301 CTR_CRYPT(y, y, 16);
302 memcpy(tag, y, tag_len);
304 return (0);
308 * Authenticated encryption
310 int mbedtls_ccm_star_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length,
311 const unsigned char *iv, size_t iv_len,
312 const unsigned char *add, size_t add_len,
313 const unsigned char *input, unsigned char *output,
314 unsigned char *tag, size_t tag_len) {
315 CCM_VALIDATE_RET(ctx != NULL);
316 CCM_VALIDATE_RET(iv != NULL);
317 CCM_VALIDATE_RET(add_len == 0 || add != NULL);
318 CCM_VALIDATE_RET(length == 0 || input != NULL);
319 CCM_VALIDATE_RET(length == 0 || output != NULL);
320 CCM_VALIDATE_RET(tag_len == 0 || tag != NULL);
321 return (ccm_auth_crypt(ctx, CCM_ENCRYPT, length, iv, iv_len,
322 add, add_len, input, output, tag, tag_len));
325 int mbedtls_ccm_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length,
326 const unsigned char *iv, size_t iv_len,
327 const unsigned char *add, size_t add_len,
328 const unsigned char *input, unsigned char *output,
329 unsigned char *tag, size_t tag_len) {
330 CCM_VALIDATE_RET(ctx != NULL);
331 CCM_VALIDATE_RET(iv != NULL);
332 CCM_VALIDATE_RET(add_len == 0 || add != NULL);
333 CCM_VALIDATE_RET(length == 0 || input != NULL);
334 CCM_VALIDATE_RET(length == 0 || output != NULL);
335 CCM_VALIDATE_RET(tag_len == 0 || tag != NULL);
336 if (tag_len == 0)
337 return (MBEDTLS_ERR_CCM_BAD_INPUT);
339 return (mbedtls_ccm_star_encrypt_and_tag(ctx, length, iv, iv_len, add,
340 add_len, input, output, tag, tag_len));
344 * Authenticated decryption
346 int mbedtls_ccm_star_auth_decrypt(mbedtls_ccm_context *ctx, size_t length,
347 const unsigned char *iv, size_t iv_len,
348 const unsigned char *add, size_t add_len,
349 const unsigned char *input, unsigned char *output,
350 const unsigned char *tag, size_t tag_len) {
351 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
352 unsigned char check_tag[16];
353 unsigned char i;
354 int diff;
356 CCM_VALIDATE_RET(ctx != NULL);
357 CCM_VALIDATE_RET(iv != NULL);
358 CCM_VALIDATE_RET(add_len == 0 || add != NULL);
359 CCM_VALIDATE_RET(length == 0 || input != NULL);
360 CCM_VALIDATE_RET(length == 0 || output != NULL);
361 CCM_VALIDATE_RET(tag_len == 0 || tag != NULL);
363 if ((ret = ccm_auth_crypt(ctx, CCM_DECRYPT, length,
364 iv, iv_len, add, add_len,
365 input, output, check_tag, tag_len)) != 0) {
366 return (ret);
369 /* Check tag in "constant-time" */
370 for (diff = 0, i = 0; i < tag_len; i++)
371 diff |= tag[i] ^ check_tag[i];
373 if (diff != 0) {
374 mbedtls_platform_zeroize(output, length);
375 return (MBEDTLS_ERR_CCM_AUTH_FAILED);
378 return (0);
381 int mbedtls_ccm_auth_decrypt(mbedtls_ccm_context *ctx, size_t length,
382 const unsigned char *iv, size_t iv_len,
383 const unsigned char *add, size_t add_len,
384 const unsigned char *input, unsigned char *output,
385 const unsigned char *tag, size_t tag_len) {
386 CCM_VALIDATE_RET(ctx != NULL);
387 CCM_VALIDATE_RET(iv != NULL);
388 CCM_VALIDATE_RET(add_len == 0 || add != NULL);
389 CCM_VALIDATE_RET(length == 0 || input != NULL);
390 CCM_VALIDATE_RET(length == 0 || output != NULL);
391 CCM_VALIDATE_RET(tag_len == 0 || tag != NULL);
393 if (tag_len == 0)
394 return (MBEDTLS_ERR_CCM_BAD_INPUT);
396 return (mbedtls_ccm_star_auth_decrypt(ctx, length, iv, iv_len, add,
397 add_len, input, output, tag, tag_len));
399 #endif /* !MBEDTLS_CCM_ALT */
401 #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
403 * Examples 1 to 3 from SP800-38C Appendix C
406 #define NB_TESTS 3
407 #define CCM_SELFTEST_PT_MAX_LEN 24
408 #define CCM_SELFTEST_CT_MAX_LEN 32
410 * The data is the same for all tests, only the used length changes
412 static const unsigned char key_test_data[] = {
413 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
414 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f
417 static const unsigned char iv_test_data[] = {
418 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
419 0x18, 0x19, 0x1a, 0x1b
422 static const unsigned char ad_test_data[] = {
423 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
424 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
425 0x10, 0x11, 0x12, 0x13
428 static const unsigned char msg_test_data[CCM_SELFTEST_PT_MAX_LEN] = {
429 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
430 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
431 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
434 static const size_t iv_len_test_data [NB_TESTS] = { 7, 8, 12 };
435 static const size_t add_len_test_data[NB_TESTS] = { 8, 16, 20 };
436 static const size_t msg_len_test_data[NB_TESTS] = { 4, 16, 24 };
437 static const size_t tag_len_test_data[NB_TESTS] = { 4, 6, 8 };
439 static const unsigned char res_test_data[NB_TESTS][CCM_SELFTEST_CT_MAX_LEN] = {
440 { 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d },
442 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62,
443 0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d,
444 0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd
447 0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a,
448 0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b,
449 0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5,
450 0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51
454 int mbedtls_ccm_self_test(int verbose) {
455 mbedtls_ccm_context ctx;
457 * Some hardware accelerators require the input and output buffers
458 * would be in RAM, because the flash is not accessible.
459 * Use buffers on the stack to hold the test vectors data.
461 unsigned char plaintext[CCM_SELFTEST_PT_MAX_LEN];
462 unsigned char ciphertext[CCM_SELFTEST_CT_MAX_LEN];
463 size_t i;
464 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
466 mbedtls_ccm_init(&ctx);
468 if (mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key_test_data,
469 8 * sizeof key_test_data) != 0) {
470 if (verbose != 0)
471 mbedtls_printf(" CCM: setup failed");
473 return (1);
476 for (i = 0; i < NB_TESTS; i++) {
477 if (verbose != 0)
478 mbedtls_printf(" CCM-AES #%u: ", (unsigned int) i + 1);
480 memset(plaintext, 0, CCM_SELFTEST_PT_MAX_LEN);
481 memset(ciphertext, 0, CCM_SELFTEST_CT_MAX_LEN);
482 memcpy(plaintext, msg_test_data, msg_len_test_data[i]);
484 ret = mbedtls_ccm_encrypt_and_tag(&ctx, msg_len_test_data[i],
485 iv_test_data, iv_len_test_data[i],
486 ad_test_data, add_len_test_data[i],
487 plaintext, ciphertext,
488 ciphertext + msg_len_test_data[i],
489 tag_len_test_data[i]);
491 if (ret != 0 ||
492 memcmp(ciphertext, res_test_data[i],
493 msg_len_test_data[i] + tag_len_test_data[i]) != 0) {
494 if (verbose != 0)
495 mbedtls_printf("failed\n");
497 return (1);
499 memset(plaintext, 0, CCM_SELFTEST_PT_MAX_LEN);
501 ret = mbedtls_ccm_auth_decrypt(&ctx, msg_len_test_data[i],
502 iv_test_data, iv_len_test_data[i],
503 ad_test_data, add_len_test_data[i],
504 ciphertext, plaintext,
505 ciphertext + msg_len_test_data[i],
506 tag_len_test_data[i]);
508 if (ret != 0 ||
509 memcmp(plaintext, msg_test_data, msg_len_test_data[i]) != 0) {
510 if (verbose != 0)
511 mbedtls_printf("failed\n");
513 return (1);
516 if (verbose != 0)
517 mbedtls_printf("passed\n");
520 mbedtls_ccm_free(&ctx);
522 if (verbose != 0)
523 mbedtls_printf("\n");
525 return (0);
528 #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
530 #endif /* MBEDTLS_CCM_C */