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