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