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