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