1 /* 2 * Implementation of NIST SP 800-38F key wrapping, supporting KW and KWP modes 3 * only 4 * 5 * Copyright The Mbed TLS Contributors 6 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 7 */ 8 /* 9 * Definition of Key Wrapping: 10 * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf 11 * RFC 3394 "Advanced Encryption Standard (AES) Key Wrap Algorithm" 12 * RFC 5649 "Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm" 13 * 14 * Note: RFC 3394 defines different methodology for intermediate operations for 15 * the wrapping and unwrapping operation than the definition in NIST SP 800-38F. 16 */ 17 18 #include "common.h" 19 20 #if defined(MBEDTLS_NIST_KW_C) 21 22 #include "mbedtls/nist_kw.h" 23 #include "mbedtls/platform_util.h" 24 #include "mbedtls/error.h" 25 #include "mbedtls/constant_time.h" 26 #include "constant_time_internal.h" 27 28 #include <stdint.h> 29 #include <string.h> 30 31 #include "mbedtls/platform.h" 32 33 #if !defined(MBEDTLS_NIST_KW_ALT) 34 35 #define KW_SEMIBLOCK_LENGTH 8 36 #define MIN_SEMIBLOCKS_COUNT 3 37 38 /*! The 64-bit default integrity check value (ICV) for KW mode. */ 39 static const unsigned char NIST_KW_ICV1[] = { 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6 }; 40 /*! The 32-bit default integrity check value (ICV) for KWP mode. */ 41 static const unsigned char NIST_KW_ICV2[] = { 0xA6, 0x59, 0x59, 0xA6 }; 42 43 /* 44 * Initialize context 45 */ 46 void mbedtls_nist_kw_init(mbedtls_nist_kw_context *ctx) 47 { 48 memset(ctx, 0, sizeof(mbedtls_nist_kw_context)); 49 } 50 51 int mbedtls_nist_kw_setkey(mbedtls_nist_kw_context *ctx, 52 mbedtls_cipher_id_t cipher, 53 const unsigned char *key, 54 unsigned int keybits, 55 const int is_wrap) 56 { 57 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 58 const mbedtls_cipher_info_t *cipher_info; 59 60 cipher_info = mbedtls_cipher_info_from_values(cipher, 61 keybits, 62 MBEDTLS_MODE_ECB); 63 if (cipher_info == NULL) { 64 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 65 } 66 67 if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) { 68 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 69 } 70 71 /* 72 * SP 800-38F currently defines AES cipher as the only block cipher allowed: 73 * "For KW and KWP, the underlying block cipher shall be approved, and the 74 * block size shall be 128 bits. Currently, the AES block cipher, with key 75 * lengths of 128, 192, or 256 bits, is the only block cipher that fits 76 * this profile." 77 * Currently we don't support other 128 bit block ciphers for key wrapping, 78 * such as Camellia and Aria. 79 */ 80 if (cipher != MBEDTLS_CIPHER_ID_AES) { 81 return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 82 } 83 84 mbedtls_cipher_free(&ctx->cipher_ctx); 85 86 if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) { 87 return ret; 88 } 89 90 if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits, 91 is_wrap ? MBEDTLS_ENCRYPT : 92 MBEDTLS_DECRYPT) 93 ) != 0) { 94 return ret; 95 } 96 97 return 0; 98 } 99 100 /* 101 * Free context 102 */ 103 void mbedtls_nist_kw_free(mbedtls_nist_kw_context *ctx) 104 { 105 if (ctx == NULL) { 106 return; 107 } 108 109 mbedtls_cipher_free(&ctx->cipher_ctx); 110 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_nist_kw_context)); 111 } 112 113 /* 114 * Helper function for Xoring the uint64_t "t" with the encrypted A. 115 * Defined in NIST SP 800-38F section 6.1 116 */ 117 static void calc_a_xor_t(unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t) 118 { 119 size_t i = 0; 120 for (i = 0; i < sizeof(t); i++) { 121 A[i] ^= (t >> ((sizeof(t) - 1 - i) * 8)) & 0xff; 122 } 123 } 124 125 /* 126 * KW-AE as defined in SP 800-38F section 6.2 127 * KWP-AE as defined in SP 800-38F section 6.3 128 */ 129 int mbedtls_nist_kw_wrap(mbedtls_nist_kw_context *ctx, 130 mbedtls_nist_kw_mode_t mode, 131 const unsigned char *input, size_t in_len, 132 unsigned char *output, size_t *out_len, size_t out_size) 133 { 134 int ret = 0; 135 size_t semiblocks = 0; 136 size_t s; 137 size_t olen, padlen = 0; 138 uint64_t t = 0; 139 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; 140 unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; 141 142 *out_len = 0; 143 /* 144 * Generate the String to work on 145 */ 146 if (mode == MBEDTLS_KW_MODE_KW) { 147 if (out_size < in_len + KW_SEMIBLOCK_LENGTH) { 148 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 149 } 150 151 /* 152 * According to SP 800-38F Table 1, the plaintext length for KW 153 * must be between 2 to 2^54-1 semiblocks inclusive. 154 */ 155 if (in_len < 16 || 156 #if SIZE_MAX > 0x1FFFFFFFFFFFFF8 157 in_len > 0x1FFFFFFFFFFFFF8 || 158 #endif 159 in_len % KW_SEMIBLOCK_LENGTH != 0) { 160 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 161 } 162 163 memcpy(output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH); 164 memmove(output + KW_SEMIBLOCK_LENGTH, input, in_len); 165 } else { 166 if (in_len % 8 != 0) { 167 padlen = (8 - (in_len % 8)); 168 } 169 170 if (out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen) { 171 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 172 } 173 174 /* 175 * According to SP 800-38F Table 1, the plaintext length for KWP 176 * must be between 1 and 2^32-1 octets inclusive. 177 */ 178 if (in_len < 1 179 #if SIZE_MAX > 0xFFFFFFFF 180 || in_len > 0xFFFFFFFF 181 #endif 182 ) { 183 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 184 } 185 186 memcpy(output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2); 187 MBEDTLS_PUT_UINT32_BE((in_len & 0xffffffff), output, 188 KW_SEMIBLOCK_LENGTH / 2); 189 190 memcpy(output + KW_SEMIBLOCK_LENGTH, input, in_len); 191 memset(output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen); 192 } 193 semiblocks = ((in_len + padlen) / KW_SEMIBLOCK_LENGTH) + 1; 194 195 s = 6 * (semiblocks - 1); 196 197 if (mode == MBEDTLS_KW_MODE_KWP 198 && in_len <= KW_SEMIBLOCK_LENGTH) { 199 memcpy(inbuff, output, 16); 200 ret = mbedtls_cipher_update(&ctx->cipher_ctx, 201 inbuff, 16, output, &olen); 202 if (ret != 0) { 203 goto cleanup; 204 } 205 } else { 206 unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH; 207 unsigned char *A = output; 208 209 /* 210 * Do the wrapping function W, as defined in RFC 3394 section 2.2.1 211 */ 212 if (semiblocks < MIN_SEMIBLOCKS_COUNT) { 213 ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 214 goto cleanup; 215 } 216 217 /* Calculate intermediate values */ 218 for (t = 1; t <= s; t++) { 219 memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH); 220 memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH); 221 222 ret = mbedtls_cipher_update(&ctx->cipher_ctx, 223 inbuff, 16, outbuff, &olen); 224 if (ret != 0) { 225 goto cleanup; 226 } 227 228 memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH); 229 calc_a_xor_t(A, t); 230 231 memcpy(R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH); 232 R2 += KW_SEMIBLOCK_LENGTH; 233 if (R2 >= output + (semiblocks * KW_SEMIBLOCK_LENGTH)) { 234 R2 = output + KW_SEMIBLOCK_LENGTH; 235 } 236 } 237 } 238 239 *out_len = semiblocks * KW_SEMIBLOCK_LENGTH; 240 241 cleanup: 242 243 if (ret != 0) { 244 memset(output, 0, semiblocks * KW_SEMIBLOCK_LENGTH); 245 } 246 mbedtls_platform_zeroize(inbuff, KW_SEMIBLOCK_LENGTH * 2); 247 mbedtls_platform_zeroize(outbuff, KW_SEMIBLOCK_LENGTH * 2); 248 249 return ret; 250 } 251 252 /* 253 * W-1 function as defined in RFC 3394 section 2.2.2 254 * This function assumes the following: 255 * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH. 256 * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH. 257 * 3. Minimal number of semiblocks is 3. 258 * 4. A is a buffer to hold the first semiblock of the input buffer. 259 */ 260 static int unwrap(mbedtls_nist_kw_context *ctx, 261 const unsigned char *input, size_t semiblocks, 262 unsigned char A[KW_SEMIBLOCK_LENGTH], 263 unsigned char *output, size_t *out_len) 264 { 265 int ret = 0; 266 const size_t s = 6 * (semiblocks - 1); 267 size_t olen; 268 uint64_t t = 0; 269 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; 270 unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; 271 unsigned char *R = NULL; 272 *out_len = 0; 273 274 if (semiblocks < MIN_SEMIBLOCKS_COUNT) { 275 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 276 } 277 278 memcpy(A, input, KW_SEMIBLOCK_LENGTH); 279 memmove(output, input + KW_SEMIBLOCK_LENGTH, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH); 280 R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH; 281 282 /* Calculate intermediate values */ 283 for (t = s; t >= 1; t--) { 284 calc_a_xor_t(A, t); 285 286 memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH); 287 memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH); 288 289 ret = mbedtls_cipher_update(&ctx->cipher_ctx, 290 inbuff, 16, outbuff, &olen); 291 if (ret != 0) { 292 goto cleanup; 293 } 294 295 memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH); 296 297 /* Set R as LSB64 of outbuff */ 298 memcpy(R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH); 299 300 if (R == output) { 301 R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH; 302 } else { 303 R -= KW_SEMIBLOCK_LENGTH; 304 } 305 } 306 307 *out_len = (semiblocks - 1) * KW_SEMIBLOCK_LENGTH; 308 309 cleanup: 310 if (ret != 0) { 311 memset(output, 0, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH); 312 } 313 mbedtls_platform_zeroize(inbuff, sizeof(inbuff)); 314 mbedtls_platform_zeroize(outbuff, sizeof(outbuff)); 315 316 return ret; 317 } 318 319 /* 320 * KW-AD as defined in SP 800-38F section 6.2 321 * KWP-AD as defined in SP 800-38F section 6.3 322 */ 323 int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx, 324 mbedtls_nist_kw_mode_t mode, 325 const unsigned char *input, size_t in_len, 326 unsigned char *output, size_t *out_len, size_t out_size) 327 { 328 int ret = 0; 329 size_t olen; 330 unsigned char A[KW_SEMIBLOCK_LENGTH]; 331 int diff; 332 333 *out_len = 0; 334 if (out_size < in_len - KW_SEMIBLOCK_LENGTH) { 335 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 336 } 337 338 if (mode == MBEDTLS_KW_MODE_KW) { 339 /* 340 * According to SP 800-38F Table 1, the ciphertext length for KW 341 * must be between 3 to 2^54 semiblocks inclusive. 342 */ 343 if (in_len < 24 || 344 #if SIZE_MAX > 0x200000000000000 345 in_len > 0x200000000000000 || 346 #endif 347 in_len % KW_SEMIBLOCK_LENGTH != 0) { 348 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 349 } 350 351 ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH, 352 A, output, out_len); 353 if (ret != 0) { 354 goto cleanup; 355 } 356 357 /* Check ICV in "constant-time" */ 358 diff = mbedtls_ct_memcmp(NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH); 359 360 if (diff != 0) { 361 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; 362 goto cleanup; 363 } 364 365 } else if (mode == MBEDTLS_KW_MODE_KWP) { 366 size_t padlen = 0; 367 uint32_t Plen; 368 /* 369 * According to SP 800-38F Table 1, the ciphertext length for KWP 370 * must be between 2 to 2^29 semiblocks inclusive. 371 */ 372 if (in_len < KW_SEMIBLOCK_LENGTH * 2 || 373 #if SIZE_MAX > 0x100000000 374 in_len > 0x100000000 || 375 #endif 376 in_len % KW_SEMIBLOCK_LENGTH != 0) { 377 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 378 } 379 380 if (in_len == KW_SEMIBLOCK_LENGTH * 2) { 381 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; 382 ret = mbedtls_cipher_update(&ctx->cipher_ctx, 383 input, 16, outbuff, &olen); 384 if (ret != 0) { 385 goto cleanup; 386 } 387 388 memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH); 389 memcpy(output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH); 390 mbedtls_platform_zeroize(outbuff, sizeof(outbuff)); 391 *out_len = KW_SEMIBLOCK_LENGTH; 392 } else { 393 /* in_len >= KW_SEMIBLOCK_LENGTH * 3 */ 394 ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH, 395 A, output, out_len); 396 if (ret != 0) { 397 goto cleanup; 398 } 399 } 400 401 /* Check ICV in "constant-time" */ 402 diff = mbedtls_ct_memcmp(NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2); 403 404 if (diff != 0) { 405 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; 406 } 407 408 Plen = MBEDTLS_GET_UINT32_BE(A, KW_SEMIBLOCK_LENGTH / 2); 409 410 /* 411 * Plen is the length of the plaintext, when the input is valid. 412 * If Plen is larger than the plaintext and padding, padlen will be 413 * larger than 8, because of the type wrap around. 414 */ 415 padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen; 416 ret = mbedtls_ct_error_if(mbedtls_ct_uint_gt(padlen, 7), 417 MBEDTLS_ERR_CIPHER_AUTH_FAILED, ret); 418 padlen &= 7; 419 420 /* Check padding in "constant-time" */ 421 const uint8_t zero[KW_SEMIBLOCK_LENGTH] = { 0 }; 422 diff = mbedtls_ct_memcmp_partial( 423 &output[*out_len - KW_SEMIBLOCK_LENGTH], zero, 424 KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH - padlen, 0); 425 426 if (diff != 0) { 427 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; 428 } 429 430 if (ret != 0) { 431 goto cleanup; 432 } 433 memset(output + Plen, 0, padlen); 434 *out_len = Plen; 435 } else { 436 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 437 goto cleanup; 438 } 439 440 cleanup: 441 if (ret != 0) { 442 memset(output, 0, *out_len); 443 *out_len = 0; 444 } 445 446 mbedtls_platform_zeroize(&diff, sizeof(diff)); 447 mbedtls_platform_zeroize(A, sizeof(A)); 448 449 return ret; 450 } 451 452 #endif /* !MBEDTLS_NIST_KW_ALT */ 453 454 #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) 455 456 /* 457 * Test vectors taken from NIST 458 * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW 459 */ 460 static const unsigned int key_len[] = { 461 16, 462 #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) 463 24, 464 32 465 #endif 466 }; 467 468 static const unsigned char kw_key[][32] = { 469 { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2, 470 0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 }, 471 #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) 472 { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b, 473 0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d, 474 0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 }, 475 { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25, 476 0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33, 477 0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d, 478 0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 } 479 #endif 480 }; 481 482 static const unsigned char kw_msg[][40] = { 483 { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea, 484 0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f }, 485 #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) 486 { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb, 487 0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d, 488 0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45, 489 0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d, 490 0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c }, 491 { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7, 492 0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8, 493 0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 } 494 #endif 495 }; 496 497 static const size_t kw_msg_len[] = { 498 16, 499 #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) 500 40, 501 24 502 #endif 503 }; 504 static const size_t kw_out_len[] = { 505 24, 506 #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) 507 48, 508 32 509 #endif 510 }; 511 static const unsigned char kw_res[][48] = { 512 { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d, 513 0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3, 514 0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb }, 515 #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) 516 { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91, 517 0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec, 518 0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d, 519 0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8, 520 0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19, 521 0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d }, 522 { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d, 523 0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87, 524 0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9, 525 0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 } 526 #endif 527 }; 528 529 static const unsigned char kwp_key[][32] = { 530 { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a, 531 0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 }, 532 #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) 533 { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98, 534 0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7, 535 0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 }, 536 { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5, 537 0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f, 538 0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae, 539 0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a } 540 #endif 541 }; 542 543 static const unsigned char kwp_msg[][31] = { 544 { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8, 545 0x96 }, 546 #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) 547 { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb, 548 0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19, 549 0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66, 550 0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f }, 551 { 0xd1 } 552 #endif 553 }; 554 static const size_t kwp_msg_len[] = { 555 9, 556 #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) 557 31, 558 1 559 #endif 560 }; 561 562 static const unsigned char kwp_res[][48] = { 563 { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e, 564 0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7, 565 0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 }, 566 #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) 567 { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13, 568 0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88, 569 0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63, 570 0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90, 571 0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 }, 572 { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd, 573 0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 } 574 #endif 575 }; 576 static const size_t kwp_out_len[] = { 577 24, 578 #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) 579 40, 580 16 581 #endif 582 }; 583 584 int mbedtls_nist_kw_self_test(int verbose) 585 { 586 mbedtls_nist_kw_context ctx; 587 unsigned char out[48]; 588 size_t olen; 589 int i; 590 int ret = 0; 591 mbedtls_nist_kw_init(&ctx); 592 593 /* 594 * KW mode 595 */ 596 { 597 static const int num_tests = sizeof(kw_key) / sizeof(*kw_key); 598 599 for (i = 0; i < num_tests; i++) { 600 if (verbose != 0) { 601 mbedtls_printf(" KW-AES-%u ", (unsigned int) key_len[i] * 8); 602 } 603 604 ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, 605 kw_key[i], key_len[i] * 8, 1); 606 if (ret != 0) { 607 if (verbose != 0) { 608 mbedtls_printf(" KW: setup failed "); 609 } 610 611 goto end; 612 } 613 614 ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, kw_msg[i], 615 kw_msg_len[i], out, &olen, sizeof(out)); 616 if (ret != 0 || kw_out_len[i] != olen || 617 memcmp(out, kw_res[i], kw_out_len[i]) != 0) { 618 if (verbose != 0) { 619 mbedtls_printf("failed. "); 620 } 621 622 ret = 1; 623 goto end; 624 } 625 626 if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, 627 kw_key[i], key_len[i] * 8, 0)) 628 != 0) { 629 if (verbose != 0) { 630 mbedtls_printf(" KW: setup failed "); 631 } 632 633 goto end; 634 } 635 636 ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW, 637 out, olen, out, &olen, sizeof(out)); 638 639 if (ret != 0 || olen != kw_msg_len[i] || 640 memcmp(out, kw_msg[i], kw_msg_len[i]) != 0) { 641 if (verbose != 0) { 642 mbedtls_printf("failed\n"); 643 } 644 645 ret = 1; 646 goto end; 647 } 648 649 if (verbose != 0) { 650 mbedtls_printf(" passed\n"); 651 } 652 } 653 } 654 655 /* 656 * KWP mode 657 */ 658 { 659 static const int num_tests = sizeof(kwp_key) / sizeof(*kwp_key); 660 661 for (i = 0; i < num_tests; i++) { 662 olen = sizeof(out); 663 if (verbose != 0) { 664 mbedtls_printf(" KWP-AES-%u ", (unsigned int) key_len[i] * 8); 665 } 666 667 ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i], 668 key_len[i] * 8, 1); 669 if (ret != 0) { 670 if (verbose != 0) { 671 mbedtls_printf(" KWP: setup failed "); 672 } 673 674 goto end; 675 } 676 ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i], 677 kwp_msg_len[i], out, &olen, sizeof(out)); 678 679 if (ret != 0 || kwp_out_len[i] != olen || 680 memcmp(out, kwp_res[i], kwp_out_len[i]) != 0) { 681 if (verbose != 0) { 682 mbedtls_printf("failed. "); 683 } 684 685 ret = 1; 686 goto end; 687 } 688 689 if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, 690 kwp_key[i], key_len[i] * 8, 0)) 691 != 0) { 692 if (verbose != 0) { 693 mbedtls_printf(" KWP: setup failed "); 694 } 695 696 goto end; 697 } 698 699 ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KWP, out, 700 olen, out, &olen, sizeof(out)); 701 702 if (ret != 0 || olen != kwp_msg_len[i] || 703 memcmp(out, kwp_msg[i], kwp_msg_len[i]) != 0) { 704 if (verbose != 0) { 705 mbedtls_printf("failed. "); 706 } 707 708 ret = 1; 709 goto end; 710 } 711 712 if (verbose != 0) { 713 mbedtls_printf(" passed\n"); 714 } 715 } 716 } 717 end: 718 mbedtls_nist_kw_free(&ctx); 719 720 if (verbose != 0) { 721 mbedtls_printf("\n"); 722 } 723 724 return ret; 725 } 726 727 #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ 728 729 #endif /* MBEDTLS_NIST_KW_C */ 730