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