1 /* 2 * NIST SP800-38C compliant CCM implementation 3 * 4 * Copyright The Mbed TLS Contributors 5 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6 */ 7 8 /* 9 * Definition of CCM: 10 * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf 11 * RFC 3610 "Counter with CBC-MAC (CCM)" 12 * 13 * Related: 14 * RFC 5116 "An Interface and Algorithms for Authenticated Encryption" 15 */ 16 17 #include "common.h" 18 19 #if defined(MBEDTLS_CCM_C) 20 21 #include "mbedtls/ccm.h" 22 #include "mbedtls/platform_util.h" 23 #include "mbedtls/error.h" 24 #include "mbedtls/constant_time.h" 25 26 #if defined(MBEDTLS_BLOCK_CIPHER_C) 27 #include "block_cipher_internal.h" 28 #endif 29 30 #include <string.h> 31 32 #if defined(MBEDTLS_PLATFORM_C) 33 #include "mbedtls/platform.h" 34 #else 35 #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) 36 #include <stdio.h> 37 #define mbedtls_printf printf 38 #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ 39 #endif /* MBEDTLS_PLATFORM_C */ 40 41 #if !defined(MBEDTLS_CCM_ALT) 42 43 44 /* 45 * Initialize context 46 */ 47 void mbedtls_ccm_init(mbedtls_ccm_context *ctx) 48 { 49 memset(ctx, 0, sizeof(mbedtls_ccm_context)); 50 } 51 52 int mbedtls_ccm_setkey(mbedtls_ccm_context *ctx, 53 mbedtls_cipher_id_t cipher, 54 const unsigned char *key, 55 unsigned int keybits) 56 { 57 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 58 59 #if defined(MBEDTLS_BLOCK_CIPHER_C) 60 mbedtls_block_cipher_free(&ctx->block_cipher_ctx); 61 62 if ((ret = mbedtls_block_cipher_setup(&ctx->block_cipher_ctx, cipher)) != 0) { 63 return MBEDTLS_ERR_CCM_BAD_INPUT; 64 } 65 66 if ((ret = mbedtls_block_cipher_setkey(&ctx->block_cipher_ctx, key, keybits)) != 0) { 67 return MBEDTLS_ERR_CCM_BAD_INPUT; 68 } 69 #else 70 const mbedtls_cipher_info_t *cipher_info; 71 72 cipher_info = mbedtls_cipher_info_from_values(cipher, keybits, 73 MBEDTLS_MODE_ECB); 74 if (cipher_info == NULL) { 75 return MBEDTLS_ERR_CCM_BAD_INPUT; 76 } 77 78 if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) { 79 return MBEDTLS_ERR_CCM_BAD_INPUT; 80 } 81 82 mbedtls_cipher_free(&ctx->cipher_ctx); 83 84 if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) { 85 return ret; 86 } 87 88 if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits, 89 MBEDTLS_ENCRYPT)) != 0) { 90 return ret; 91 } 92 #endif 93 94 return ret; 95 } 96 97 /* 98 * Free context 99 */ 100 void mbedtls_ccm_free(mbedtls_ccm_context *ctx) 101 { 102 if (ctx == NULL) { 103 return; 104 } 105 #if defined(MBEDTLS_BLOCK_CIPHER_C) 106 mbedtls_block_cipher_free(&ctx->block_cipher_ctx); 107 #else 108 mbedtls_cipher_free(&ctx->cipher_ctx); 109 #endif 110 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ccm_context)); 111 } 112 113 #define CCM_STATE__CLEAR 0 114 #define CCM_STATE__STARTED (1 << 0) 115 #define CCM_STATE__LENGTHS_SET (1 << 1) 116 #define CCM_STATE__AUTH_DATA_STARTED (1 << 2) 117 #define CCM_STATE__AUTH_DATA_FINISHED (1 << 3) 118 #define CCM_STATE__ERROR (1 << 4) 119 120 /* 121 * Encrypt or decrypt a partial block with CTR 122 */ 123 static int mbedtls_ccm_crypt(mbedtls_ccm_context *ctx, 124 size_t offset, size_t use_len, 125 const unsigned char *input, 126 unsigned char *output) 127 { 128 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 129 unsigned char tmp_buf[16] = { 0 }; 130 131 #if defined(MBEDTLS_BLOCK_CIPHER_C) 132 ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->ctr, tmp_buf); 133 #else 134 size_t olen = 0; 135 ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->ctr, 16, tmp_buf, &olen); 136 #endif 137 if (ret != 0) { 138 ctx->state |= CCM_STATE__ERROR; 139 mbedtls_platform_zeroize(tmp_buf, sizeof(tmp_buf)); 140 return ret; 141 } 142 143 mbedtls_xor(output, input, tmp_buf + offset, use_len); 144 145 mbedtls_platform_zeroize(tmp_buf, sizeof(tmp_buf)); 146 return ret; 147 } 148 149 static void mbedtls_ccm_clear_state(mbedtls_ccm_context *ctx) 150 { 151 ctx->state = CCM_STATE__CLEAR; 152 memset(ctx->y, 0, 16); 153 memset(ctx->ctr, 0, 16); 154 } 155 156 static int ccm_calculate_first_block_if_ready(mbedtls_ccm_context *ctx) 157 { 158 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 159 unsigned char i; 160 size_t len_left; 161 #if !defined(MBEDTLS_BLOCK_CIPHER_C) 162 size_t olen; 163 #endif 164 165 /* length calculation can be done only after both 166 * mbedtls_ccm_starts() and mbedtls_ccm_set_lengths() have been executed 167 */ 168 if (!(ctx->state & CCM_STATE__STARTED) || !(ctx->state & CCM_STATE__LENGTHS_SET)) { 169 return 0; 170 } 171 172 /* CCM expects non-empty tag. 173 * CCM* allows empty tag. For CCM* without tag, the tag calculation is skipped. 174 */ 175 if (ctx->tag_len == 0) { 176 if (ctx->mode == MBEDTLS_CCM_STAR_ENCRYPT || ctx->mode == MBEDTLS_CCM_STAR_DECRYPT) { 177 ctx->plaintext_len = 0; 178 return 0; 179 } else { 180 return MBEDTLS_ERR_CCM_BAD_INPUT; 181 } 182 } 183 184 /* 185 * First block: 186 * 0 .. 0 flags 187 * 1 .. iv_len nonce (aka iv) - set by: mbedtls_ccm_starts() 188 * iv_len+1 .. 15 length 189 * 190 * With flags as (bits): 191 * 7 0 192 * 6 add present? 193 * 5 .. 3 (t - 2) / 2 194 * 2 .. 0 q - 1 195 */ 196 ctx->y[0] |= (ctx->add_len > 0) << 6; 197 ctx->y[0] |= ((ctx->tag_len - 2) / 2) << 3; 198 ctx->y[0] |= ctx->q - 1; 199 200 for (i = 0, len_left = ctx->plaintext_len; i < ctx->q; i++, len_left >>= 8) { 201 ctx->y[15-i] = MBEDTLS_BYTE_0(len_left); 202 } 203 204 if (len_left > 0) { 205 ctx->state |= CCM_STATE__ERROR; 206 return MBEDTLS_ERR_CCM_BAD_INPUT; 207 } 208 209 /* Start CBC-MAC with first block*/ 210 #if defined(MBEDTLS_BLOCK_CIPHER_C) 211 ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y); 212 #else 213 ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen); 214 #endif 215 if (ret != 0) { 216 ctx->state |= CCM_STATE__ERROR; 217 return ret; 218 } 219 220 return 0; 221 } 222 223 int mbedtls_ccm_starts(mbedtls_ccm_context *ctx, 224 int mode, 225 const unsigned char *iv, 226 size_t iv_len) 227 { 228 /* Also implies q is within bounds */ 229 if (iv_len < 7 || iv_len > 13) { 230 return MBEDTLS_ERR_CCM_BAD_INPUT; 231 } 232 233 ctx->mode = mode; 234 ctx->q = 16 - 1 - (unsigned char) iv_len; 235 236 /* 237 * Prepare counter block for encryption: 238 * 0 .. 0 flags 239 * 1 .. iv_len nonce (aka iv) 240 * iv_len+1 .. 15 counter (initially 1) 241 * 242 * With flags as (bits): 243 * 7 .. 3 0 244 * 2 .. 0 q - 1 245 */ 246 memset(ctx->ctr, 0, 16); 247 ctx->ctr[0] = ctx->q - 1; 248 memcpy(ctx->ctr + 1, iv, iv_len); 249 memset(ctx->ctr + 1 + iv_len, 0, ctx->q); 250 ctx->ctr[15] = 1; 251 252 /* 253 * See ccm_calculate_first_block_if_ready() for block layout description 254 */ 255 memcpy(ctx->y + 1, iv, iv_len); 256 257 ctx->state |= CCM_STATE__STARTED; 258 return ccm_calculate_first_block_if_ready(ctx); 259 } 260 261 int mbedtls_ccm_set_lengths(mbedtls_ccm_context *ctx, 262 size_t total_ad_len, 263 size_t plaintext_len, 264 size_t tag_len) 265 { 266 /* 267 * Check length requirements: SP800-38C A.1 268 * Additional requirement: a < 2^16 - 2^8 to simplify the code. 269 * 'length' checked later (when writing it to the first block) 270 * 271 * Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4). 272 */ 273 if (tag_len == 2 || tag_len > 16 || tag_len % 2 != 0) { 274 return MBEDTLS_ERR_CCM_BAD_INPUT; 275 } 276 277 if (total_ad_len >= 0xFF00) { 278 return MBEDTLS_ERR_CCM_BAD_INPUT; 279 } 280 281 ctx->plaintext_len = plaintext_len; 282 ctx->add_len = total_ad_len; 283 ctx->tag_len = tag_len; 284 ctx->processed = 0; 285 286 ctx->state |= CCM_STATE__LENGTHS_SET; 287 return ccm_calculate_first_block_if_ready(ctx); 288 } 289 290 int mbedtls_ccm_update_ad(mbedtls_ccm_context *ctx, 291 const unsigned char *add, 292 size_t add_len) 293 { 294 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 295 size_t use_len, offset; 296 #if !defined(MBEDTLS_BLOCK_CIPHER_C) 297 size_t olen; 298 #endif 299 300 if (ctx->state & CCM_STATE__ERROR) { 301 return MBEDTLS_ERR_CCM_BAD_INPUT; 302 } 303 304 if (add_len > 0) { 305 if (ctx->state & CCM_STATE__AUTH_DATA_FINISHED) { 306 return MBEDTLS_ERR_CCM_BAD_INPUT; 307 } 308 309 if (!(ctx->state & CCM_STATE__AUTH_DATA_STARTED)) { 310 if (add_len > ctx->add_len) { 311 return MBEDTLS_ERR_CCM_BAD_INPUT; 312 } 313 314 ctx->y[0] ^= (unsigned char) ((ctx->add_len >> 8) & 0xFF); 315 ctx->y[1] ^= (unsigned char) ((ctx->add_len) & 0xFF); 316 317 ctx->state |= CCM_STATE__AUTH_DATA_STARTED; 318 } else if (ctx->processed + add_len > ctx->add_len) { 319 return MBEDTLS_ERR_CCM_BAD_INPUT; 320 } 321 322 while (add_len > 0) { 323 offset = (ctx->processed + 2) % 16; /* account for y[0] and y[1] 324 * holding total auth data length */ 325 use_len = 16 - offset; 326 327 if (use_len > add_len) { 328 use_len = add_len; 329 } 330 331 mbedtls_xor(ctx->y + offset, ctx->y + offset, add, use_len); 332 333 ctx->processed += use_len; 334 add_len -= use_len; 335 add += use_len; 336 337 if (use_len + offset == 16 || ctx->processed == ctx->add_len) { 338 #if defined(MBEDTLS_BLOCK_CIPHER_C) 339 ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y); 340 #else 341 ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen); 342 #endif 343 if (ret != 0) { 344 ctx->state |= CCM_STATE__ERROR; 345 return ret; 346 } 347 } 348 } 349 350 if (ctx->processed == ctx->add_len) { 351 ctx->state |= CCM_STATE__AUTH_DATA_FINISHED; 352 ctx->processed = 0; // prepare for mbedtls_ccm_update() 353 } 354 } 355 356 return 0; 357 } 358 359 int mbedtls_ccm_update(mbedtls_ccm_context *ctx, 360 const unsigned char *input, size_t input_len, 361 unsigned char *output, size_t output_size, 362 size_t *output_len) 363 { 364 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 365 unsigned char i; 366 size_t use_len, offset; 367 #if !defined(MBEDTLS_BLOCK_CIPHER_C) 368 size_t olen; 369 #endif 370 371 unsigned char local_output[16]; 372 373 if (ctx->state & CCM_STATE__ERROR) { 374 return MBEDTLS_ERR_CCM_BAD_INPUT; 375 } 376 377 /* Check against plaintext length only if performing operation with 378 * authentication 379 */ 380 if (ctx->tag_len != 0 && ctx->processed + input_len > ctx->plaintext_len) { 381 return MBEDTLS_ERR_CCM_BAD_INPUT; 382 } 383 384 if (output_size < input_len) { 385 return MBEDTLS_ERR_CCM_BAD_INPUT; 386 } 387 *output_len = input_len; 388 389 ret = 0; 390 391 while (input_len > 0) { 392 offset = ctx->processed % 16; 393 394 use_len = 16 - offset; 395 396 if (use_len > input_len) { 397 use_len = input_len; 398 } 399 400 ctx->processed += use_len; 401 402 if (ctx->mode == MBEDTLS_CCM_ENCRYPT || \ 403 ctx->mode == MBEDTLS_CCM_STAR_ENCRYPT) { 404 mbedtls_xor(ctx->y + offset, ctx->y + offset, input, use_len); 405 406 if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) { 407 #if defined(MBEDTLS_BLOCK_CIPHER_C) 408 ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y); 409 #else 410 ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen); 411 #endif 412 if (ret != 0) { 413 ctx->state |= CCM_STATE__ERROR; 414 goto exit; 415 } 416 } 417 418 ret = mbedtls_ccm_crypt(ctx, offset, use_len, input, output); 419 if (ret != 0) { 420 goto exit; 421 } 422 } 423 424 if (ctx->mode == MBEDTLS_CCM_DECRYPT || \ 425 ctx->mode == MBEDTLS_CCM_STAR_DECRYPT) { 426 /* Since output may be in shared memory, we cannot be sure that 427 * it will contain what we wrote to it. Therefore, we should avoid using 428 * it as input to any operations. 429 * Write decrypted data to local_output to avoid using output variable as 430 * input in the XOR operation for Y. 431 */ 432 ret = mbedtls_ccm_crypt(ctx, offset, use_len, input, local_output); 433 if (ret != 0) { 434 goto exit; 435 } 436 437 mbedtls_xor(ctx->y + offset, ctx->y + offset, local_output, use_len); 438 439 memcpy(output, local_output, use_len); 440 441 if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) { 442 #if defined(MBEDTLS_BLOCK_CIPHER_C) 443 ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y); 444 #else 445 ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen); 446 #endif 447 if (ret != 0) { 448 ctx->state |= CCM_STATE__ERROR; 449 goto exit; 450 } 451 } 452 } 453 454 if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) { 455 for (i = 0; i < ctx->q; i++) { 456 if (++(ctx->ctr)[15-i] != 0) { 457 break; 458 } 459 } 460 } 461 462 input_len -= use_len; 463 input += use_len; 464 output += use_len; 465 } 466 467 exit: 468 mbedtls_platform_zeroize(local_output, 16); 469 470 return ret; 471 } 472 473 int mbedtls_ccm_finish(mbedtls_ccm_context *ctx, 474 unsigned char *tag, size_t tag_len) 475 { 476 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 477 unsigned char i; 478 479 if (ctx->state & CCM_STATE__ERROR) { 480 return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 481 } 482 483 if (ctx->add_len > 0 && !(ctx->state & CCM_STATE__AUTH_DATA_FINISHED)) { 484 return MBEDTLS_ERR_CCM_BAD_INPUT; 485 } 486 487 if (ctx->plaintext_len > 0 && ctx->processed != ctx->plaintext_len) { 488 return MBEDTLS_ERR_CCM_BAD_INPUT; 489 } 490 491 /* 492 * Authentication: reset counter and crypt/mask internal tag 493 */ 494 for (i = 0; i < ctx->q; i++) { 495 ctx->ctr[15-i] = 0; 496 } 497 498 ret = mbedtls_ccm_crypt(ctx, 0, 16, ctx->y, ctx->y); 499 if (ret != 0) { 500 return ret; 501 } 502 if (tag != NULL) { 503 memcpy(tag, ctx->y, tag_len); 504 } 505 mbedtls_ccm_clear_state(ctx); 506 507 return 0; 508 } 509 510 /* 511 * Authenticated encryption or decryption 512 */ 513 static int ccm_auth_crypt(mbedtls_ccm_context *ctx, int mode, size_t length, 514 const unsigned char *iv, size_t iv_len, 515 const unsigned char *add, size_t add_len, 516 const unsigned char *input, unsigned char *output, 517 unsigned char *tag, size_t tag_len) 518 { 519 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 520 size_t olen; 521 522 if ((ret = mbedtls_ccm_starts(ctx, mode, iv, iv_len)) != 0) { 523 return ret; 524 } 525 526 if ((ret = mbedtls_ccm_set_lengths(ctx, add_len, length, tag_len)) != 0) { 527 return ret; 528 } 529 530 if ((ret = mbedtls_ccm_update_ad(ctx, add, add_len)) != 0) { 531 return ret; 532 } 533 534 if ((ret = mbedtls_ccm_update(ctx, input, length, 535 output, length, &olen)) != 0) { 536 return ret; 537 } 538 539 if ((ret = mbedtls_ccm_finish(ctx, tag, tag_len)) != 0) { 540 return ret; 541 } 542 543 return 0; 544 } 545 546 /* 547 * Authenticated encryption 548 */ 549 int mbedtls_ccm_star_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length, 550 const unsigned char *iv, size_t iv_len, 551 const unsigned char *add, size_t add_len, 552 const unsigned char *input, unsigned char *output, 553 unsigned char *tag, size_t tag_len) 554 { 555 return ccm_auth_crypt(ctx, MBEDTLS_CCM_STAR_ENCRYPT, length, iv, iv_len, 556 add, add_len, input, output, tag, tag_len); 557 } 558 559 int mbedtls_ccm_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length, 560 const unsigned char *iv, size_t iv_len, 561 const unsigned char *add, size_t add_len, 562 const unsigned char *input, unsigned char *output, 563 unsigned char *tag, size_t tag_len) 564 { 565 return ccm_auth_crypt(ctx, MBEDTLS_CCM_ENCRYPT, length, iv, iv_len, 566 add, add_len, input, output, tag, tag_len); 567 } 568 569 /* 570 * Authenticated decryption 571 */ 572 static int mbedtls_ccm_compare_tags(const unsigned char *tag1, 573 const unsigned char *tag2, 574 size_t tag_len) 575 { 576 /* Check tag in "constant-time" */ 577 int diff = mbedtls_ct_memcmp(tag1, tag2, tag_len); 578 579 if (diff != 0) { 580 return MBEDTLS_ERR_CCM_AUTH_FAILED; 581 } 582 583 return 0; 584 } 585 586 static int ccm_auth_decrypt(mbedtls_ccm_context *ctx, int mode, size_t length, 587 const unsigned char *iv, size_t iv_len, 588 const unsigned char *add, size_t add_len, 589 const unsigned char *input, unsigned char *output, 590 const unsigned char *tag, size_t tag_len) 591 { 592 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 593 unsigned char check_tag[16]; 594 595 if ((ret = ccm_auth_crypt(ctx, mode, length, 596 iv, iv_len, add, add_len, 597 input, output, check_tag, tag_len)) != 0) { 598 return ret; 599 } 600 601 if ((ret = mbedtls_ccm_compare_tags(tag, check_tag, tag_len)) != 0) { 602 mbedtls_platform_zeroize(output, length); 603 return ret; 604 } 605 606 return 0; 607 } 608 609 int mbedtls_ccm_star_auth_decrypt(mbedtls_ccm_context *ctx, size_t length, 610 const unsigned char *iv, size_t iv_len, 611 const unsigned char *add, size_t add_len, 612 const unsigned char *input, unsigned char *output, 613 const unsigned char *tag, size_t tag_len) 614 { 615 return ccm_auth_decrypt(ctx, MBEDTLS_CCM_STAR_DECRYPT, length, 616 iv, iv_len, add, add_len, 617 input, output, tag, tag_len); 618 } 619 620 int mbedtls_ccm_auth_decrypt(mbedtls_ccm_context *ctx, size_t length, 621 const unsigned char *iv, size_t iv_len, 622 const unsigned char *add, size_t add_len, 623 const unsigned char *input, unsigned char *output, 624 const unsigned char *tag, size_t tag_len) 625 { 626 return ccm_auth_decrypt(ctx, MBEDTLS_CCM_DECRYPT, length, 627 iv, iv_len, add, add_len, 628 input, output, tag, tag_len); 629 } 630 #endif /* !MBEDTLS_CCM_ALT */ 631 632 #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_CCM_GCM_CAN_AES) 633 /* 634 * Examples 1 to 3 from SP800-38C Appendix C 635 */ 636 637 #define NB_TESTS 3 638 #define CCM_SELFTEST_PT_MAX_LEN 24 639 #define CCM_SELFTEST_CT_MAX_LEN 32 640 /* 641 * The data is the same for all tests, only the used length changes 642 */ 643 static const unsigned char key_test_data[] = { 644 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 645 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f 646 }; 647 648 static const unsigned char iv_test_data[] = { 649 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 650 0x18, 0x19, 0x1a, 0x1b 651 }; 652 653 static const unsigned char ad_test_data[] = { 654 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 655 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 656 0x10, 0x11, 0x12, 0x13 657 }; 658 659 static const unsigned char msg_test_data[CCM_SELFTEST_PT_MAX_LEN] = { 660 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 661 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 662 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 663 }; 664 665 static const size_t iv_len_test_data[NB_TESTS] = { 7, 8, 12 }; 666 static const size_t add_len_test_data[NB_TESTS] = { 8, 16, 20 }; 667 static const size_t msg_len_test_data[NB_TESTS] = { 4, 16, 24 }; 668 static const size_t tag_len_test_data[NB_TESTS] = { 4, 6, 8 }; 669 670 static const unsigned char res_test_data[NB_TESTS][CCM_SELFTEST_CT_MAX_LEN] = { 671 { 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d }, 672 { 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62, 673 0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d, 674 0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd }, 675 { 0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a, 676 0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b, 677 0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5, 678 0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 } 679 }; 680 681 int mbedtls_ccm_self_test(int verbose) 682 { 683 mbedtls_ccm_context ctx; 684 /* 685 * Some hardware accelerators require the input and output buffers 686 * would be in RAM, because the flash is not accessible. 687 * Use buffers on the stack to hold the test vectors data. 688 */ 689 unsigned char plaintext[CCM_SELFTEST_PT_MAX_LEN]; 690 unsigned char ciphertext[CCM_SELFTEST_CT_MAX_LEN]; 691 size_t i; 692 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 693 694 mbedtls_ccm_init(&ctx); 695 696 if (mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key_test_data, 697 8 * sizeof(key_test_data)) != 0) { 698 if (verbose != 0) { 699 mbedtls_printf(" CCM: setup failed"); 700 } 701 702 return 1; 703 } 704 705 for (i = 0; i < NB_TESTS; i++) { 706 if (verbose != 0) { 707 mbedtls_printf(" CCM-AES #%u: ", (unsigned int) i + 1); 708 } 709 710 memset(plaintext, 0, CCM_SELFTEST_PT_MAX_LEN); 711 memset(ciphertext, 0, CCM_SELFTEST_CT_MAX_LEN); 712 memcpy(plaintext, msg_test_data, msg_len_test_data[i]); 713 714 ret = mbedtls_ccm_encrypt_and_tag(&ctx, msg_len_test_data[i], 715 iv_test_data, iv_len_test_data[i], 716 ad_test_data, add_len_test_data[i], 717 plaintext, ciphertext, 718 ciphertext + msg_len_test_data[i], 719 tag_len_test_data[i]); 720 721 if (ret != 0 || 722 memcmp(ciphertext, res_test_data[i], 723 msg_len_test_data[i] + tag_len_test_data[i]) != 0) { 724 if (verbose != 0) { 725 mbedtls_printf("failed\n"); 726 } 727 728 return 1; 729 } 730 memset(plaintext, 0, CCM_SELFTEST_PT_MAX_LEN); 731 732 ret = mbedtls_ccm_auth_decrypt(&ctx, msg_len_test_data[i], 733 iv_test_data, iv_len_test_data[i], 734 ad_test_data, add_len_test_data[i], 735 ciphertext, plaintext, 736 ciphertext + msg_len_test_data[i], 737 tag_len_test_data[i]); 738 739 if (ret != 0 || 740 memcmp(plaintext, msg_test_data, msg_len_test_data[i]) != 0) { 741 if (verbose != 0) { 742 mbedtls_printf("failed\n"); 743 } 744 745 return 1; 746 } 747 748 if (verbose != 0) { 749 mbedtls_printf("passed\n"); 750 } 751 } 752 753 mbedtls_ccm_free(&ctx); 754 755 if (verbose != 0) { 756 mbedtls_printf("\n"); 757 } 758 759 return 0; 760 } 761 762 #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ 763 764 #endif /* MBEDTLS_CCM_C */ 765