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